"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
-<!-- 2024-10-29 Tue 21:35 -->
+<!-- 2025-05-31 Sat 22:27 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>A Small Institute</title>
secure and private campus that can function with or without the
Internet.
</p>
-<div id="outline-container-org56d00a8" class="outline-2">
-<h2 id="org56d00a8"><span class="section-number-2">1.</span> Overview</h2>
+<div id="outline-container-org12986b7" class="outline-2">
+<h2 id="org12986b7"><span class="section-number-2">1.</span> Overview</h2>
<div class="outline-text-2" id="text-1">
<p>
This small institute has a public server on the Internet, Front, that
members off campus.
</p>
-<pre class="example" id="org42c266c">
+<pre class="example" id="org9ebcfa4">
=
_|||_
=-The-Institute-=
</p>
</div>
</div>
-<div id="outline-container-org4c498be" class="outline-2">
-<h2 id="org4c498be"><span class="section-number-2">2.</span> Caveats</h2>
+<div id="outline-container-org68fcf87" class="outline-2">
+<h2 id="org68fcf87"><span class="section-number-2">2.</span> Caveats</h2>
<div class="outline-text-2" id="text-2">
<p>
This small institute prizes its privacy, so there is little or no
</p>
</div>
</div>
-<div id="outline-container-orgd99d86a" class="outline-2">
-<h2 id="orgd99d86a"><span class="section-number-2">3.</span> The Services</h2>
+<div id="outline-container-org1120238" class="outline-2">
+<h2 id="org1120238"><span class="section-number-2">3.</span> The Services</h2>
<div class="outline-text-2" id="text-3">
<p>
The small institute's network is designed to provide a number of
reference particulars first introduced in the following chapter.
</p>
</div>
-<div id="outline-container-org12ea1d0" class="outline-3">
-<h3 id="org12ea1d0"><span class="section-number-3">3.1.</span> The Name Service</h3>
+<div id="outline-container-org189ccc3" class="outline-3">
+<h3 id="org189ccc3"><span class="section-number-3">3.1.</span> The Name Service</h3>
<div class="outline-text-3" id="text-3-1">
<p>
The institute has a public domain, e.g. <code>small.example.org</code>, and a
</p>
</div>
</div>
-<div id="outline-container-org22a6220" class="outline-3">
-<h3 id="org22a6220"><span class="section-number-3">3.2.</span> The Email Service</h3>
+<div id="outline-container-org73635f2" class="outline-3">
+<h3 id="org73635f2"><span class="section-number-3">3.2.</span> The Email Service</h3>
<div class="outline-text-3" id="text-3-2">
<p>
Front provides the public SMTP (Simple Mail Transfer Protocol) service
</p>
<div class="org-src-container">
-Example Small Institute SPF Record<pre class="src src-conf"><span class="org-variable-name">TXT v</span>=spf1 ip4:159.65.75.60 -all
-</pre>
+Example Small Institute SPF Record<pre class="src src-conf"><code><span class="org-variable-name">TXT v</span>=spf1 ip4:159.65.75.60 -all
+</code></pre>
</div>
<p>
configurations wherever <code><<postfix-message-size>></code> appears.
</p>
</div>
-<div id="outline-container-orge0db702" class="outline-4">
-<h4 id="orge0db702"><span class="section-number-4">3.2.1.</span> The Postfix Configurations</h4>
+<div id="outline-container-org630ebd0" class="outline-4">
+<h4 id="org630ebd0"><span class="section-number-4">3.2.1.</span> The Postfix Configurations</h4>
<div class="outline-text-4" id="text-3-2-1">
<p>
The institute aims to accommodate encrypted email containing short
</p>
<div class="org-src-container">
-<code>postfix-message-size</code><pre class="src src-conf" id="orgb73b70b">- { p: message_size_limit, v: 104857600 }
-</pre>
+<code>postfix-message-size</code><pre class="src src-conf" id="org76e6614"><code>- { p: message_size_limit, v: 104857600 }
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-queue-times</code><pre class="src src-conf" id="org3ddc4d4">- { p: delay_warning_time, v: 1h }
+<code>postfix-queue-times</code><pre class="src src-conf" id="orge1f6b9f"><code>- { p: delay_warning_time, v: 1h }
- { p: maximal_queue_lifetime, v: 4h }
- { p: bounce_queue_lifetime, v: 4h }
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-relaying</code><pre class="src src-conf" id="org211f1c0">- p: smtpd_relay_restrictions
+<code>postfix-relaying</code><pre class="src src-conf" id="orgfc41c7f"><code>- p: smtpd_relay_restrictions
v: permit_mynetworks reject_unauth_destination
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-maildir</code><pre class="src src-conf" id="orga0931ea">- { p: home_mailbox, v: Maildir/ }
-</pre>
+<code>postfix-maildir</code><pre class="src src-conf" id="org38b410e"><code>- { p: home_mailbox, v: Maildir/ }
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-org768dc52" class="outline-4">
-<h4 id="org768dc52"><span class="section-number-4">3.2.2.</span> The Dovecot Configurations</h4>
+<div id="outline-container-org4c351b3" class="outline-4">
+<h4 id="org4c351b3"><span class="section-number-4">3.2.2.</span> The Dovecot Configurations</h4>
<div class="outline-text-4" id="text-3-2-2">
<p>
The Dovecot settings on both Front and Core disable POP and require
</p>
<div class="org-src-container">
-<code>dovecot-tls</code><pre class="src src-conf" id="org574da80"><span class="org-variable-name">protocols</span> = imap
+<code>dovecot-tls</code><pre class="src src-conf" id="org9aa23d4"><code><span class="org-variable-name">protocols</span> = imap
<span class="org-variable-name">ssl</span> = required
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>dovecot-ports</code><pre class="src src-conf" id="orga82cd71"><span class="org-type">service imap-login</span> {
+<code>dovecot-ports</code><pre class="src src-conf" id="orgf5fbf4b"><code><span class="org-type">service imap-login</span> {
<span class="org-type">inet_listener imap</span> {
<span class="org-variable-name">port</span> = 0
}
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>dovecot-maildir</code><pre class="src src-conf" id="orgf0e66f0"><span class="org-variable-name">mail_location</span> = maildir:~/Maildir
-</pre>
+<code>dovecot-maildir</code><pre class="src src-conf" id="org4ab71c8"><code><span class="org-variable-name">mail_location</span> = maildir:~/Maildir
+</code></pre>
</div>
<p>
</div>
</div>
</div>
-<div id="outline-container-org43cbe17" class="outline-3">
-<h3 id="org43cbe17"><span class="section-number-3">3.3.</span> The Web Services</h3>
+<div id="outline-container-orgf659a90" class="outline-3">
+<h3 id="orgf659a90"><span class="section-number-3">3.3.</span> The Web Services</h3>
<div class="outline-text-3" id="text-3-3">
<p>
Front provides the public HTTP service that serves institute web pages
at e.g. <code>https://small.example.org/</code>. The small institute initially
runs with a self-signed, "snake oil" server certificate, causing
browsers to warn of possible fraud, but this certificate is easily
-replaced by one signed by a recognized authority, as discussed in <a href="#org9240129">The
+replaced by one signed by a recognized authority, as discussed in <a href="#org1024107">The
Front Role</a>.
</p>
once they are complete and tested.</dd>
<dt><code>http://core/</code></dt><dd>is the Debian default site. The institute does
not munge this site, to avoid conflicts with Debian-packaged web
-services (e.g. Nextcloud, Zoneminder, MythTV's MythWeb).</dd>
+services (e.g. Nextcloud, AgentDVR, MythTV's MythWeb).</dd>
</dl>
<p>
</p>
</div>
</div>
-<div id="outline-container-org71fc0ac" class="outline-3">
-<h3 id="org71fc0ac"><span class="section-number-3">3.4.</span> The Cloud Service</h3>
+<div id="outline-container-orgd0834d2" class="outline-3">
+<h3 id="orgd0834d2"><span class="section-number-3">3.4.</span> The Cloud Service</h3>
<div class="outline-text-3" id="text-3-4">
<p>
Core runs Nextcloud to provide a private institute cloud at
-<code>http://core.small.private/nextcloud/</code>. It is managed manually per
+<code>https://core.small.private/nextcloud/</code>. It is managed manually per
<a href="https://docs.nextcloud.com/server/latest/admin_manual/">The Nextcloud Server Administration Guide</a>. The code <i>and</i> data,
including especially database dumps, are stored in <q>/Nextcloud/</q> which
-is included in Core's backup procedure as described in <a href="#org431068a">Backups</a>. The
+is included in Core's backup procedure as described in <a href="#org2a7965d">Backups</a>. The
default Apache2 configuration expects to find the web scripts in
<q>/var/www/nextcloud/</q>, so the institute symbolically links this to
<q>/Nextcloud/nextcloud/</q>.
</p>
</div>
</div>
-<div id="outline-container-orgc2baf19" class="outline-3">
-<h3 id="orgc2baf19"><span class="section-number-3">3.5.</span> The VPN Services</h3>
+<div id="outline-container-org1ea6412" class="outline-3">
+<h3 id="org1ea6412"><span class="section-number-3">3.5.</span> The VPN Services</h3>
<div class="outline-text-3" id="text-3-5">
<p>
The institute's public and campus VPNs have many common configuration
options that are discussed here. These are included, with example
certificates and network addresses, in the complete server
-configurations of <a href="#org9240129">The Front Role</a> and <a href="#org72d6fde">The Gate Role</a>, as well as the
-matching client configurations in <a href="#orge7ebc83">The Core Role</a> and the <q>.ovpn</q> files
-generated by <a href="#org0ad53cf">The Client Command</a>. The configurations are based on the
+configurations of <a href="#org1024107">The Front Role</a> and <a href="#org936487d">The Gate Role</a>, as well as the
+matching client configurations in <a href="#orge6d718e">The Core Role</a> and the <q>.ovpn</q> files
+generated by <a href="#orgdc36b90">The Client Command</a>. The configurations are based on the
documentation for OpenVPN v2.4: the <code>openvpn(8)</code> manual page and <a href="https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/">this
web page</a>.
</p>
</div>
-<div id="outline-container-org5b24b6e" class="outline-4">
-<h4 id="org5b24b6e"><span class="section-number-4">3.5.1.</span> The VPN Configuration Options</h4>
+<div id="outline-container-orgf621905" class="outline-4">
+<h4 id="orgf621905"><span class="section-number-4">3.5.1.</span> The VPN Configuration Options</h4>
<div class="outline-text-4" id="text-3-5-1">
<p>
The institute VPNs use UDP on a subnet topology (rather than
</p>
<div class="org-src-container">
-<code>openvpn-dev-mode</code><pre class="src src-conf" id="orgea7339c">dev-type tun
+<code>openvpn-dev-mode</code><pre class="src src-conf" id="org2722342"><code>dev-type tun
dev ovpn
topology subnet
client-to-client
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>openvpn-keepalive</code><pre class="src src-conf" id="orgb8aba90">keepalive 10 120
-</pre>
+<code>openvpn-keepalive</code><pre class="src src-conf" id="orgfe45128"><code>keepalive 10 120
+</code></pre>
</div>
<p>
-As mentioned in <a href="#org12ea1d0">The Name Service</a>, the institute uses a campus name
+As mentioned in <a href="#org189ccc3">The Name Service</a>, the institute uses a campus name
server. OpenVPN is instructed to push its address and the campus
search domain.
</p>
<div class="org-src-container">
-<code>openvpn-dns</code><pre class="src src-conf" id="org3448fff">push <span class="org-string">"dhcp-option DOMAIN {{ domain_priv }}"</span>
+<code>openvpn-dns</code><pre class="src src-conf" id="org035983f"><code>push <span class="org-string">"dhcp-option DOMAIN {{ domain_priv }}"</span>
push <span class="org-string">"dhcp-option DNS {{ core_addr }}"</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>openvpn-drop-priv</code><pre class="src src-conf" id="org5cd7a6f">user nobody
+<code>openvpn-drop-priv</code><pre class="src src-conf" id="orge4d440d"><code>user nobody
group nogroup
persist-key
persist-tun
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>openvpn-crypt</code><pre class="src src-conf" id="orgbf610a1">cipher AES-256-GCM
+<code>openvpn-crypt</code><pre class="src src-conf" id="orgb13e625"><code>cipher AES-256-GCM
auth SHA256
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>openvpn-max</code><pre class="src src-conf" id="org7c68569">max-clients 20
-</pre>
+<code>openvpn-max</code><pre class="src src-conf" id="orgd79815a"><code>max-clients 20
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>openvpn-debug</code><pre class="src src-conf" id="orgddb99ce">ifconfig-pool-persist ipp.txt
+<code>openvpn-debug</code><pre class="src src-conf" id="org59b4726"><code>ifconfig-pool-persist ipp.txt
status openvpn-status.log
verb 3
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-org54da6ed" class="outline-3">
-<h3 id="org54da6ed"><span class="section-number-3">3.6.</span> Accounts</h3>
+<div id="outline-container-orga38c5ed" class="outline-3">
+<h3 id="orga38c5ed"><span class="section-number-3">3.6.</span> Accounts</h3>
<div class="outline-text-3" id="text-3-6">
<p>
A small institute has just a handful of members. For simplicity (and
thus security) static configuration files are preferred over complex
account management systems, LDAP, Active Directory, and the like. The
Ansible scripts configure the same set of user accounts on Core and
-Front. <a href="#org1c6f4a8">The Institute Commands</a> (e.g. <code>./inst new dick</code>) capture the
+Front. <a href="#org5db480b">The Institute Commands</a> (e.g. <code>./inst new dick</code>) capture the
processes of enrolling, modifying and retiring members of the
institute. They update the administrator's membership roll, and run
Ansible to create (and disable) accounts on Core, Front, Nextcloud,
all be private (readable and writable only by the owner) by default.
</p>
</div>
-<div id="outline-container-org00e3480" class="outline-4">
-<h4 id="org00e3480"><span class="section-number-4">3.6.1.</span> The Administration Accounts</h4>
+<div id="outline-container-org4a8c2dc" class="outline-4">
+<h4 id="org4a8c2dc"><span class="section-number-4">3.6.1.</span> The Administration Accounts</h4>
<div class="outline-text-4" id="text-3-6-1">
<p>
The institute avoids the use of the <code>root</code> account (<code>uid 0</code>) because
and programs as <code>root</code>. When installation of a Debian OS leaves the
host with no user accounts, just the <code>root</code> account, the next step is
to create a system administrator's account named <code>sysadm</code> and to give
-it permission to use the <code>sudo</code> command (e.g. as described in <a href="#org7661483">The
+it permission to use the <code>sudo</code> command (e.g. as described in <a href="#org9282df0">The
Front Machine</a>). When installation prompts for the name of an
initial, privileged user account the same name is given (e.g. as
-described in <a href="#org8d60b7b">The Core Machine</a>). Installation may <i>not</i> prompt and
+described in <a href="#orgae4ce75">The Core Machine</a>). Installation may <i>not</i> prompt and
still create an initial user account with a distribution specific name
(e.g. <code>pi</code>). Any name can be used as long as it is provided as the
value of <code>ansible_user</code> in <a href="hosts"><q>hosts</q></a>. Its password is specified by a
vault-encrypted variable in the <a href="Secret/become.yml"><q>Secret/become.yml</q></a> file. (The
-<a href="hosts"><q>hosts</q></a> and <a href="Secret/become.yml"><q>Secret/become.yml</q></a> files are described in <a href="#orgff33e02">The Ansible
+<a href="hosts"><q>hosts</q></a> and <a href="Secret/become.yml"><q>Secret/become.yml</q></a> files are described in <a href="#orgda31017">The Ansible
Configuration</a>.)
</p>
</div>
</div>
-<div id="outline-container-org726a9e8" class="outline-4">
-<h4 id="org726a9e8"><span class="section-number-4">3.6.2.</span> The Monkey Accounts</h4>
+<div id="outline-container-org9470e9b" class="outline-4">
+<h4 id="org9470e9b"><span class="section-number-4">3.6.2.</span> The Monkey Accounts</h4>
<div class="outline-text-4" id="text-3-6-2">
<p>
The institute's Core uses a special account named <code>monkey</code> to run
</div>
</div>
</div>
-<div id="outline-container-org6519b0c" class="outline-3">
-<h3 id="org6519b0c"><span class="section-number-3">3.7.</span> Keys</h3>
+<div id="outline-container-org1c1be46" class="outline-3">
+<h3 id="org1c1be46"><span class="section-number-3">3.7.</span> Keys</h3>
<div class="outline-text-3" id="text-3-7">
<p>
The institute keeps its "master secrets" in an encrypted
rsync -a Secret/ Secret3/
</pre>
-
<p>
This is out of consideration for the fragility of USB drives, and the
importance of a certain SSH private key, without which the
</p>
</div>
</div>
-<div id="outline-container-org431068a" class="outline-3">
-<h3 id="org431068a"><span class="section-number-3">3.8.</span> Backups</h3>
+<div id="outline-container-org2a7965d" class="outline-3">
+<h3 id="org2a7965d"><span class="section-number-3">3.8.</span> Backups</h3>
<div class="outline-text-3" id="text-3-8">
<p>
The small institute backs up its data, but not so much so that nothing
Given the <code>-n</code> flag, the script does a "pre-sync" which does not pause
Nextcloud nor dump its DB. A pre-sync gets the big file (video)
copies done while Nextcloud continues to run. A follow-up <code>sudo
-backup</code> (<i>without</i> <code>-n</code>) produces the complete copy (with all the
+backup</code>, <i>without</i> <code>-n</code>, produces the complete copy (with all the
files mentioned in the Nextcloud database dump).
</p>
<div class="org-src-container">
-<a href="private/backup"><q>private/backup</q></a><pre class="src src-sh" id="org9d5954c"><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">bash</span><span class="org-comment"> -e</span>
+<a href="private/backup"><q>private/backup</q></a><pre class="src src-sh" id="org8d148e8"><code><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">bash</span><span class="org-comment"> -e</span>
<span class="org-comment-delimiter">#</span>
<span class="org-comment-delimiter"># </span><span class="org-comment">DO NOT EDIT. Maintained (will be replaced) by Ansible.</span>
<span class="org-comment-delimiter">#</span>
<span class="org-builtin">echo</span> <span class="org-string">"Mounting /backup/."</span>
cryptsetup luksOpen /dev/disk/by-partlabel/Backup backup
mount /dev/mapper/backup /backup
- <span class="org-variable-name">mounted</span>=indeed
<span class="org-keyword">else</span>
<span class="org-builtin">echo</span> <span class="org-string">"Found /backup/ already mounted."</span>
- <span class="org-variable-name">mounted</span>=
<span class="org-keyword">fi</span>
<span class="org-keyword">if</span> [ <span class="org-negation-char">!</span> -d /backup/home ]
<span class="org-keyword">if</span> [ <span class="org-negation-char">!</span> $<span class="org-variable-name">presync</span> ]
<span class="org-keyword">then</span>
- <span class="org-builtin">echo</span> <span class="org-string">"Putting nextcloud into maintenance mode."</span>
+ <span class="org-builtin">echo</span> <span class="org-string">"Putting Nextcloud into maintenance mode."</span>
( <span class="org-builtin">cd</span> /Nextcloud/nextcloud/
sudo -u www-data php occ maintenance:mode --on &>/dev/null )
- <span class="org-builtin">echo</span> <span class="org-string">"Dumping nextcloud database."</span>
+ <span class="org-builtin">echo</span> <span class="org-string">"Dumping Nextcloud database."</span>
( <span class="org-builtin">cd</span> /Nextcloud/
<span class="org-builtin">umask</span> 07
- <span class="org-variable-name">BAK</span>=<span class="org-sh-quoted-exec">`date +"%Y%m%d"`</span>-dbbackup.bak.gz
+ <span class="org-variable-name">BAK</span>=<span class="org-sh-quoted-exec">`date +"%Y%m%d%H%M"`</span>-dbbackup.bak.gz
<span class="org-variable-name">CNF</span>=/Nextcloud/dbbackup.cnf
mysqldump --defaults-file=$<span class="org-variable-name">CNF</span> nextcloud | gzip > $<span class="org-variable-name">BAK</span>
- chmod 440 $<span class="org-variable-name">BAK</span> )
+ chmod 440 $<span class="org-variable-name">BAK</span>
+ ls -t1 *-dbbackup.bak.gz | tail -n +4 <span class="org-sh-escaped-newline">\</span>
+ | <span class="org-keyword">while </span><span class="org-builtin">read</span>; <span class="org-keyword">do</span> rm <span class="org-string">"$REPLY"</span>; <span class="org-keyword">done</span>
+ )
<span class="org-keyword">fi</span>
}
<span class="org-keyword">if</span> [ <span class="org-negation-char">!</span> $<span class="org-variable-name">presync</span> ]
<span class="org-keyword">then</span>
- <span class="org-builtin">echo</span> <span class="org-string">"Putting nextcloud back into service."</span>
+ <span class="org-builtin">echo</span> <span class="org-string">"Putting Nextcloud back into service."</span>
( <span class="org-builtin">cd</span> /Nextcloud/nextcloud/
sudo -u www-data php occ maintenance:mode --off &>/dev/null )
<span class="org-keyword">fi</span>
- <span class="org-keyword">if</span> [ $<span class="org-variable-name">mounted</span> ]
+ <span class="org-keyword">if</span> mountpoint -q /backup/
<span class="org-keyword">then</span>
<span class="org-builtin">echo</span> <span class="org-string">"Unmounting /backup/."</span>
umount /backup
cryptsetup luksClose backup
- <span class="org-variable-name">mounted</span>=
+ <span class="org-builtin">echo</span> <span class="org-string">"Done."</span>
+ <span class="org-builtin">echo</span> <span class="org-string">"The backup device can be safely disconnected."</span>
<span class="org-keyword">fi</span>
- <span class="org-builtin">echo</span> <span class="org-string">"Done."</span>
- <span class="org-builtin">echo</span> <span class="org-string">"The backup device can be safely disconnected."</span>
-
}
start
<span class="org-keyword">done</span>
finish
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-orgfa75f05" class="outline-2">
-<h2 id="orgfa75f05"><span class="section-number-2">4.</span> The Particulars</h2>
+<div id="outline-container-orgb4f5586" class="outline-2">
+<h2 id="orgb4f5586"><span class="section-number-2">4.</span> The Particulars</h2>
<div class="outline-text-2" id="text-4">
<p>
This chapter introduces Ansible variables intended to simplify
<p>
The example settings in this document configure VirtualBox VMs as
-described in the <a href="#org74b454f">Testing</a> chapter. For more information about how a
+described in the <a href="#org7832c43">Testing</a> chapter. For more information about how a
small institute turns the example Ansible code into a working Ansible
-configuration, see chapter <a href="#orgff33e02">The Ansible Configuration</a>.
+configuration, see chapter <a href="#orgda31017">The Ansible Configuration</a>.
</p>
</div>
-<div id="outline-container-org54548e2" class="outline-3">
-<h3 id="org54548e2"><span class="section-number-3">4.1.</span> Generic Particulars</h3>
+<div id="outline-container-org0ba16f9" class="outline-3">
+<h3 id="org0ba16f9"><span class="section-number-3">4.1.</span> Generic Particulars</h3>
<div class="outline-text-3" id="text-4-1">
<p>
The small institute's domain name is used quite frequently in the
</p>
<div class="org-src-container">
-<a href="public/vars.yml"><q>public/vars.yml</q></a><pre class="src src-conf">---
+<a href="public/vars.yml"><q>public/vars.yml</q></a><pre class="src src-conf"><code>---
domain_name: small.example.org
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">---
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>---
domain_priv: small.private
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgda60362" class="outline-3">
-<h3 id="orgda60362"><span class="section-number-3">4.2.</span> Subnets</h3>
+<div id="outline-container-org29f9840" class="outline-3">
+<h3 id="org29f9840"><span class="section-number-3">4.2.</span> Subnets</h3>
<div class="outline-text-3" id="text-4-2">
<p>
The small institute uses a private Ethernet, two VPNs, and an
</p>
<div class="org-src-container">
-<pre class="src src-emacs-lisp">(<span class="org-keyword">let</span> ((bytes
+<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">let</span> ((bytes
(<span class="org-keyword">let</span> ((i (random (+ 256 16))))
(<span class="org-keyword">if</span> (< i 256)
(list 10 i (1+ (random 254)))
(list 172 (+ 16 (- i 256)) (1+ (random 254)))))))
(format <span class="org-string">"%d.%d.%d.0/24"</span> (car bytes) (cadr bytes) (caddr bytes)))
-</pre>
+</code></pre>
</div>
-<div class="TEXT" id="org0dd8c3a">
+<div class="TEXT" id="org078b489">
<p>
=> 10.62.17.0/24
</p>
sensitive information so again the code block below "tangles" into
<a href="private/vars.yml"><q>private/vars.yml</q></a> rather than <a href="public/vars.yml"><q>public/vars.yml</q></a>. Two of the
addresses are in <code>192.168</code> subnets because they are part of a test
-configuration using mostly-default VirtualBoxes (described <a href="#org74b454f">here</a>).
+configuration using mostly-default VirtualBoxes (described <a href="#org7832c43">here</a>).
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>
private_net_cidr: 192.168.56.0/24
+wild_net_cidr: 192.168.57.0/24
public_vpn_net_cidr: 10.177.86.0/24
campus_vpn_net_cidr: 10.84.138.0/24
-gate_wifi_net_cidr: 192.168.57.0/24
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">private_net:
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>private_net:
<span class="org-string">"{{ private_net_cidr | ansible.utils.ipaddr('network') }}"</span>
private_net_mask:
<span class="org-string">"{{ private_net_cidr | ansible.utils.ipaddr('netmask') }}"</span>
-private_net_and_mask:
- <span class="org-string">"{{ private_net }} {{ private_net_mask }}"</span>
+private_net_and_mask: <span class="org-string">"{{ private_net }} {{ private_net_mask }}"</span>
public_vpn_net:
<span class="org-string">"{{ public_vpn_net_cidr | ansible.utils.ipaddr('network') }}"</span>
public_vpn_net_mask:
<span class="org-string">"{{ campus_vpn_net_cidr | ansible.utils.ipaddr('netmask') }}"</span>
campus_vpn_net_and_mask:
<span class="org-string">"{{ campus_vpn_net }} {{ campus_vpn_net_mask }}"</span>
-gate_wifi_net:
- <span class="org-string">"{{ gate_wifi_net_cidr | ansible.utils.ipaddr('network') }}"</span>
-gate_wifi_net_mask:
- <span class="org-string">"{{ gate_wifi_net_cidr | ansible.utils.ipaddr('netmask') }}"</span>
-gate_wifi_net_and_mask:
- <span class="org-string">"{{ gate_wifi_net }} {{ gate_wifi_net_mask }}"</span>
-gate_wifi_broadcast:
- <span class="org-string">"{{ gate_wifi_net_cidr | ansible.utils.ipaddr('broadcast') }}"</span>
-</pre>
+wild_net: <span class="org-string">"{{ wild_net_cidr | ansible.utils.ipaddr('network') }}"</span>
+wild_net_mask:
+ <span class="org-string">"{{ wild_net_cidr | ansible.utils.ipaddr('netmask') }}"</span>
+wild_net_and_mask: <span class="org-string">"{{ wild_net }} {{ wild_net_mask }}"</span>
+wild_net_broadcast:
+ <span class="org-string">"{{ wild_net_cidr | ansible.utils.ipaddr('broadcast') }}"</span>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="public/vars.yml"><q>public/vars.yml</q></a><pre class="src src-conf">front_addr: 192.168.15.5
-</pre>
+<a href="public/vars.yml"><q>public/vars.yml</q></a><pre class="src src-conf"><code>front_addr: 192.168.15.5
+</code></pre>
</div>
<p>
Finally, five host addresses are needed frequently in the Ansible
code. The first two are Core's and Gate's addresses on the private
Ethernet. The next two are Gate's and the campus Wi-Fi's addresses on
-the Gate-WiFi subnet, the tiny Ethernet (<code>gate_wifi_net</code>) between Gate
-and the (untrusted) campus Wi-Fi access point. The last is Front's
-address on the public VPN, perversely called <code>front_private_addr</code>.
-The following code block picks the obvious IP addresses for Core
-(host 1) and Gate (host 2).
+the "wild" subnet, the untrusted Ethernet (<code>wild_net</code>) between Gate
+and the campus Wi-Fi access point(s) and IoT appliances. The last is
+Front's address on the public VPN, perversely called
+<code>front_private_addr</code>. The following code block picks the obvious IP
+addresses for Core (host 1) and Gate (host 2).
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">core_addr_cidr: <span class="org-string">"{{ private_net_cidr | ansible.utils.ipaddr('1') }}"</span>
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>core_addr_cidr: <span class="org-string">"{{ private_net_cidr | ansible.utils.ipaddr('1') }}"</span>
gate_addr_cidr: <span class="org-string">"{{ private_net_cidr | ansible.utils.ipaddr('2') }}"</span>
-gate_wifi_addr_cidr:
- <span class="org-string">"{{ gate_wifi_net_cidr | ansible.utils.ipaddr('1') }}"</span>
-wifi_wan_addr_cidr:
- <span class="org-string">"{{ gate_wifi_net_cidr | ansible.utils.ipaddr('2') }}"</span>
+gate_wild_addr_cidr:
+ <span class="org-string">"{{ wild_net_cidr | ansible.utils.ipaddr('1') }}"</span>
+wifi_wan_addr_cidr: <span class="org-string">"{{ wild_net_cidr | ansible.utils.ipaddr('2') }}"</span>
front_private_addr_cidr:
<span class="org-string">"{{ public_vpn_net_cidr | ansible.utils.ipaddr('1') }}"</span>
core_addr: <span class="org-string">"{{ core_addr_cidr | ansible.utils.ipaddr('address') }}"</span>
gate_addr: <span class="org-string">"{{ gate_addr_cidr | ansible.utils.ipaddr('address') }}"</span>
-gate_wifi_addr:
- <span class="org-string">"{{ gate_wifi_addr_cidr | ansible.utils.ipaddr('address') }}"</span>
+gate_wild_addr:
+ <span class="org-string">"{{ gate_wild_addr_cidr | ansible.utils.ipaddr('address') }}"</span>
wifi_wan_addr:
<span class="org-string">"{{ wifi_wan_addr_cidr | ansible.utils.ipaddr('address') }}"</span>
front_private_addr:
<span class="org-string">"{{ front_private_addr_cidr | ansible.utils.ipaddr('address') }}"</span>
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-org754e9f1" class="outline-2">
-<h2 id="org754e9f1"><span class="section-number-2">5.</span> The Hardware</h2>
+<div id="outline-container-orgbf29081" class="outline-2">
+<h2 id="orgbf29081"><span class="section-number-2">5.</span> The Hardware</h2>
<div class="outline-text-2" id="text-5">
<p>
The small institute's network was built by its system administrator
using Ansible on a trusted notebook. The Ansible configuration and
scripts were generated by "tangling" the Ansible code included here.
-(<a href="#orgff33e02">The Ansible Configuration</a> describes how to do this.) The following
+(<a href="#orgda31017">The Ansible Configuration</a> describes how to do this.) The following
sections describe how Front, Gate and Core were prepared for Ansible.
</p>
</div>
-<div id="outline-container-org7661483" class="outline-3">
-<h3 id="org7661483"><span class="section-number-3">5.1.</span> The Front Machine</h3>
+<div id="outline-container-org9282df0" class="outline-3">
+<h3 id="org9282df0"><span class="section-number-3">5.1.</span> The Front Machine</h3>
<div class="outline-text-3" id="text-5-1">
<p>
Front is the small institute's public facing server, a virtual machine
Internet café using just the administrator's notebook.
</p>
</div>
-<div id="outline-container-orgb446788" class="outline-4">
-<h4 id="orgb446788"><span class="section-number-4">5.1.1.</span> A Digital Ocean Droplet</h4>
+<div id="outline-container-org7dbbd56" class="outline-4">
+<h4 id="org7dbbd56"><span class="section-number-4">5.1.1.</span> A Digital Ocean Droplet</h4>
<div class="outline-text-4" id="text-5-1-1">
<p>
The following example prepared a new front on a Digital Ocean droplet.
root@ubuntu#
</pre>
-
<p>
The freshly created Digital Ocean droplet came with just one account,
<code>root</code>, but the small institute avoids remote access to the "super
-user" account (per the policy in <a href="#org00e3480">The Administration Accounts</a>), so the
+user" account (per the policy in <a href="#org4a8c2dc">The Administration Accounts</a>), so the
administrator created a <code>sysadm</code> account with the ability to request
escalated privileges via the <code>sudo</code> command.
</p>
notebook$
</pre>
-
<p>
The password was generated by <code>gpw</code>, saved in the administrator's
password keep, and later added to <a href="Secret/become.yml"><q>Secret/become.yml</q></a> as shown below.
(Producing a working Ansible configuration with <a href="Secret/become.yml"><q>Secret/become.yml</q></a>
-file is described in <a href="#orgff33e02">The Ansible Configuration</a>.)
+file is described in <a href="#orgda31017">The Ansible Configuration</a>.)
</p>
<pre class="example">
notebook_ >>Secret/become.yml
</pre>
-
<p>
After creating the <code>sysadm</code> account on the droplet, the administrator
concatenated a personal public ssh key and the key found in
-<a href="Secret/ssh_admin/"><q>Secret/ssh_admin/</q></a> (created by <a href="#org671a111">The CA Command</a>) into an <q>admin_keys</q>
+<a href="Secret/ssh_admin/"><q>Secret/ssh_admin/</q></a> (created by <a href="#org3fe9e37">The CA Command</a>) into an <q>admin_keys</q>
file, copied it to the droplet, and installed it as the
<q>authorized_keys</q> for <code>sysadm</code>.
</p>
notebook$
</pre>
-
<p>
The Ansible configuration expects certain host keys on the new front.
The administrator should install them now, and deal with the machine's
notebook$ ssh-keygen -f ~/.ssh/known_hosts -R 159.65.75.60
</pre>
-
<p>
The last command removes the old host key from the administrator's
<q>known_hosts</q> file. The next SSH connection should ask to confirm the
root:*:18355:0:99999:7:::
</pre>
-
<p>
<i>After</i> passing the above test, the administrator disabled root logins
on the droplet. The last command below tested that root logins were
notebook$
</pre>
-
<p>
At this point the droplet was ready for configuration by Ansible.
Later, provisioned with all of Front's services <i>and</i> tested, the
</div>
</div>
</div>
-<div id="outline-container-org8d60b7b" class="outline-3">
-<h3 id="org8d60b7b"><span class="section-number-3">5.2.</span> The Core Machine</h3>
+<div id="outline-container-orgae4ce75" class="outline-3">
+<h3 id="orgae4ce75"><span class="section-number-3">5.2.</span> The Core Machine</h3>
<div class="outline-text-3" id="text-5-2">
<p>
Core is the small institute's private file, email, cloud and whatnot
freshly installed. During installation, the machine was named <code>core</code>,
no desktop or server software was installed, no root password was set,
and a privileged account named <code>sysadm</code> was created (per the policy in
-<a href="#org00e3480">The Administration Accounts</a>).
+<a href="#org4a8c2dc">The Administration Accounts</a>).
</p>
<pre class="example">
Is the information correct? [Y/n]
</pre>
-
<p>
The password was generated by <code>gpw</code>, saved in the administrator's
password keep, and later added to <a href="Secret/become.yml"><q>Secret/become.yml</q></a> as shown below.
(Producing a working Ansible configuration with <a href="Secret/become.yml"><q>Secret/become.yml</q></a>
-file is described in <a href="#orgff33e02">The Ansible Configuration</a>.)
+file is described in <a href="#orgda31017">The Ansible Configuration</a>.)
</p>
<pre class="example">
notebook_ >>Secret/become.yml
</pre>
-
<p>
With Debian freshly installed, Core needed several additional software
packages. The administrator temporarily plugged Core into a cable
_ gnupg openssh-server
</pre>
-
<p>
The Nextcloud configuration requires Apache2, MariaDB and a number of
PHP modules. Installing them while Core was on a cable modem sped up
_ libapache2-mod-php
</pre>
-
<p>
Similarly, the NAGIOS configuration requires a handful of packages
that were pre-loaded via cable modem (to test a frontier deployment).
_ nagios-nrpe-plugin
</pre>
-
<p>
Next, the administrator concatenated a personal public ssh key and the
-key found in <a href="Secret/ssh_admin/"><q>Secret/ssh_admin/</q></a> (created by <a href="#org671a111">The CA Command</a>) into an
+key found in <a href="Secret/ssh_admin/"><q>Secret/ssh_admin/</q></a> (created by <a href="#org3fe9e37">The CA Command</a>) into an
<q>admin_keys</q> file, copied it to Core, and installed it as the
<q>authorized_keys</q> for <code>sysadm</code>.
</p>
notebook$
</pre>
-
<p>
Note that the name <code>core.lan</code> should be known to the cable modem's DNS
service. An IP address might be used instead, discovered with an <code>ip
<p>
In the example command lines below, the address <code>10.227.248.1</code> was
generated by the random subnet address picking procedure described in
-<a href="#orgda60362">Subnets</a>, and is named <code>core_addr</code> in the Ansible code. The second
+<a href="#org29f9840">Subnets</a>, and is named <code>core_addr</code> in the Ansible code. The second
address, <code>10.227.248.2</code>, is the corresponding address for Gate's
Ethernet interface, and is named <code>gate_addr</code> in the Ansible
code.
sysadm@core$ sudo ip route add default via 10.227.248.2 dev enp82s0
</pre>
-
<p>
At this point Core was ready for provisioning with Ansible.
</p>
</div>
</div>
-<div id="outline-container-org24e627c" class="outline-3">
-<h3 id="org24e627c"><span class="section-number-3">5.3.</span> The Gate Machine</h3>
+<div id="outline-container-org40481f7" class="outline-3">
+<h3 id="org40481f7"><span class="section-number-3">5.3.</span> The Gate Machine</h3>
<div class="outline-text-3" id="text-5-3">
<p>
Gate is the small institute's route to the Internet, and the campus
<ol class="org-ol">
<li><code>lan</code> is its main Ethernet interface, connected to the campus's
private Ethernet switch.</li>
-<li><code>wifi</code> is its second Ethernet interface, connected to the campus
-Wi-Fi access point's WAN Ethernet interface (with a cross-over
-cable).</li>
+<li><code>wild</code> is its second Ethernet interface, connected to the
+untrusted network of campus IoT appliances and Wi-Fi access
+point(s).</li>
<li><code>isp</code> is its third network interface, connected to the campus
ISP. This could be an Ethernet device connected to a cable
modem. It could be a USB port tethered to a phone, a
campground Wi-Fi access point, etc.</li>
</ol>
-<pre class="example" id="org04f5b91">
+<pre class="example" id="orgf49687b">
=============== | ==================================================
| Premises
(Campus ISP)
+----Ethernet switch
</pre>
</div>
-<div id="outline-container-org60db67e" class="outline-4">
-<h4 id="org60db67e"><span class="section-number-4">5.3.1.</span> Alternate Gate Topology</h4>
+<div id="outline-container-org6edd1eb" class="outline-4">
+<h4 id="org6edd1eb"><span class="section-number-4">5.3.1.</span> Alternate Gate Topology</h4>
<div class="outline-text-4" id="text-5-3-1">
<p>
While Gate and Core really need to be separate machines for security
following topology.
</p>
-<pre class="example" id="org56d9e40">
+<pre class="example" id="org0d82eb6">
=============== | ==================================================
| Premises
(House ISP)
+----Ethernet switch
</pre>
<p>
-In this case Gate has two interfaces and there is no Gate-WiFi subnet.
+In this case Gate has two interfaces and there is no wild subnet
+other than the Internets themselves.
</p>
<p>
</p>
</div>
</div>
-<div id="outline-container-org78bf309" class="outline-4">
-<h4 id="org78bf309"><span class="section-number-4">5.3.2.</span> Original Gate Topology</h4>
+<div id="outline-container-orgaa27474" class="outline-4">
+<h4 id="orgaa27474"><span class="section-number-4">5.3.2.</span> Original Gate Topology</h4>
<div class="outline-text-4" id="text-5-3-2">
<p>
The Ansible code in this document is somewhat dependent on the
-physical network shown in the <a href="#org56d00a8">Overview</a> wherein Gate has three network
+physical network shown in the <a href="#org12986b7">Overview</a> wherein Gate has three network
interfaces.
</p>
freshly installed. During installation, the machine was named <code>gate</code>,
no desktop or server software was installed, no root password was set,
and a privileged account named <code>sysadm</code> was created (per the policy in
-<a href="#org00e3480">The Administration Accounts</a>).
+<a href="#org4a8c2dc">The Administration Accounts</a>).
</p>
<pre class="example">
Is the information correct? [Y/n]
</pre>
-
<p>
The password was generated by <code>gpw</code>, saved in the administrator's
password keep, and later added to <a href="Secret/become.yml"><q>Secret/become.yml</q></a> as shown below.
(Producing a working Ansible configuration with <a href="Secret/become.yml"><q>Secret/become.yml</q></a>
-file is described in <a href="#orgff33e02">The Ansible Configuration</a>.)
+file is described in <a href="#orgda31017">The Ansible Configuration</a>.)
</p>
<pre class="example">
notebook_ >>Secret/become.yml
</pre>
-
<p>
With Debian freshly installed, Gate needed a couple additional
software packages. The administrator temporarily plugged Gate into a
_ openssh-server
</pre>
-
<p>
Next, the administrator concatenated a personal public ssh key and the
-key found in <a href="Secret/ssh_admin/"><q>Secret/ssh_admin/</q></a> (created by <a href="#org671a111">The CA Command</a>) into an
+key found in <a href="Secret/ssh_admin/"><q>Secret/ssh_admin/</q></a> (created by <a href="#org3fe9e37">The CA Command</a>) into an
<q>admin_keys</q> file, copied it to Gate, and installed it as the
<q>authorized_keys</q> for <code>sysadm</code>.
</p>
notebook$
</pre>
-
<p>
Note that the name <code>gate.lan</code> should be known to the cable modem's DNS
service. An IP address might be used instead, discovered with an <code>ip
<p>
In the example command lines below, the address <code>10.227.248.2</code> was
generated by the random subnet address picking procedure described in
-<a href="#orgda60362">Subnets</a>, and is named <code>gate_addr</code> in the Ansible code.
+<a href="#org29f9840">Subnets</a>, and is named <code>gate_addr</code> in the Ansible code.
</p>
<pre class="example">
$ sudo ip address add 10.227.248.2 dev eth0
</pre>
-
<p>
Gate was also connected to the USB Ethernet dongles cabled to the
campus Wi-Fi access point and the campus ISP. The three network
adapters are known by their MAC addresses, the values of the variables
-<code>gate_lan_mac</code>, <code>gate_wifi_mac</code>, and <code>gate_isp_mac</code>. (For more
-information, see the Gate role's <a href="#org176e1b0">Configure Netplan</a> task.)
+<code>gate_lan_mac</code>, <code>gate_wild_mac</code>, and <code>gate_isp_mac</code>. (For more
+information, see the Gate role's <a href="#orgfd4af3f">Configure Netplan</a> task.)
</p>
<p>
</div>
</div>
</div>
-<div id="outline-container-orgd60dcd1" class="outline-2">
-<h2 id="orgd60dcd1"><span class="section-number-2">6.</span> The All Role</h2>
+<div id="outline-container-org72438bf" class="outline-2">
+<h2 id="org72438bf"><span class="section-number-2">6.</span> The All Role</h2>
<div class="outline-text-2" id="text-6">
<p>
The <code>all</code> role contains tasks that are executed on all of the
institute's servers. At the moment there is just the one.
</p>
</div>
-<div id="outline-container-orgbc53e05" class="outline-3">
-<h3 id="orgbc53e05"><span class="section-number-3">6.1.</span> Include Particulars</h3>
+<div id="outline-container-org204ceac" class="outline-3">
+<h3 id="org204ceac"><span class="section-number-3">6.1.</span> Include Particulars</h3>
<div class="outline-text-3" id="text-6-1">
<p>
The <code>all</code> role's task contains a reference to a common institute
particular, the institute's <code>domain_name</code>, a variable found in the
<q>public/vars.yml</q> file. Thus the first task of the <code>all</code> role is to
-include the variables defined in this file (described in <a href="#orgfa75f05">The
+include the variables defined in this file (described in <a href="#orgb4f5586">The
Particulars</a>). The code block below is the first to tangle into
<a href="roles/front/tasks/main.yml"><q>roles/all/tasks/main.yml</q></a>.
</p>
<div class="org-src-container">
-<a href="roles/front/tasks/main.yml"><q>roles/all/tasks/main.yml</q></a><pre class="src src-conf">---
+<a href="roles/front/tasks/main.yml"><q>roles/all/tasks/main.yml</q></a><pre class="src src-conf"><code>---
- name: Include public variables.
include_vars: ../public/vars.yml
tags: accounts
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgf85cc27" class="outline-3">
-<h3 id="orgf85cc27"><span class="section-number-3">6.2.</span> Enable Systemd Resolved</h3>
+<div id="outline-container-orgbfaf303" class="outline-3">
+<h3 id="orgbfaf303"><span class="section-number-3">6.2.</span> Enable Systemd Resolved</h3>
<div class="outline-text-3" id="text-6-2">
<p>
The <code>systemd-networkd</code> and <code>systemd-resolved</code> service units are not
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/all/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/all/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install systemd-resolved.
become: yes
<span class="org-variable-name">apt: pkg</span>=systemd-resolved
when:
<span class="org-variable-name">- ansible_distribution</span> == <span class="org-string">'Debian'</span>
- 12 > ansible_distribution_major_version|int
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgd3cb8ca" class="outline-3">
-<h3 id="orgd3cb8ca"><span class="section-number-3">6.3.</span> Trust Institute Certificate Authority</h3>
+<div id="outline-container-org2756611" class="outline-3">
+<h3 id="org2756611"><span class="section-number-3">6.3.</span> Trust Institute Certificate Authority</h3>
<div class="outline-text-3" id="text-6-3">
<p>
All servers should recognize the institute's Certificate Authority as
trustworthy, so its certificate is added to the set of trusted CAs on
each host. More information about how the small institute manages its
-X.509 certificates is available in <a href="#org6519b0c">Keys</a>.
+X.509 certificates is available in <a href="#org1c1be46">Keys</a>.
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/all/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/all/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Trust the institute CA.
become: yes
copy:
owner: root
group: root
notify: Update CAs.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/all/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/all/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Update CAs.
become: yes
command: update-ca-certificates
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-org9240129" class="outline-2">
-<h2 id="org9240129"><span class="section-number-2">7.</span> The Front Role</h2>
+<div id="outline-container-org1024107" class="outline-2">
+<h2 id="org1024107"><span class="section-number-2">7.</span> The Front Role</h2>
<div class="outline-text-2" id="text-7">
<p>
The <code>front</code> role installs and configures the services expected on the
institute's publicly accessible "front door": email, web, VPN. The
virtual machine is prepared with an Ubuntu Server install and remote
access to a privileged, administrator's account. (For details, see
-<a href="#org7661483">The Front Machine</a>.)
+<a href="#org9282df0">The Front Machine</a>.)
</p>
<p>
certificates signed by the institute CA.
</p>
</div>
-<div id="outline-container-org12c1e48" class="outline-3">
-<h3 id="org12c1e48"><span class="section-number-3">7.1.</span> Include Particulars</h3>
+<div id="outline-container-org92fa9ca" class="outline-3">
+<h3 id="org92fa9ca"><span class="section-number-3">7.1.</span> Include Particulars</h3>
<div class="outline-text-3" id="text-7-1">
<p>
-The first task, as in <a href="#orgd60dcd1">The All Role</a>, is to include the institute
+The first task, as in <a href="#org72438bf">The All Role</a>, is to include the institute
particulars. The <code>front</code> role refers to private variables and the
membership roll, so these are included was well.
</p>
<div class="org-src-container">
-<a href="roles/front/tasks/main.yml"><q>roles/front/tasks/main.yml</q></a><pre class="src src-conf">---
+<a href="roles/front/tasks/main.yml"><q>roles/front/tasks/main.yml</q></a><pre class="src src-conf"><code>---
- name: Include public variables.
include_vars: ../public/vars.yml
tags: accounts
- name: Include members.
include_vars: <span class="org-string">"{{ lookup('first_found', membership_rolls) }}"</span>
tags: accounts
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org4c87c3a" class="outline-3">
-<h3 id="org4c87c3a"><span class="section-number-3">7.2.</span> Configure Hostname</h3>
+<div id="outline-container-orgd1223b4" class="outline-3">
+<h3 id="orgd1223b4"><span class="section-number-3">7.2.</span> Configure Hostname</h3>
<div class="outline-text-3" id="text-7-2">
<p>
This task ensures that Front's <q>/etc/hostname</q> and <q>/etc/mailname</q> are
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">- name: Configure hostname.
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>- name: Configure hostname.
become: yes
copy:
content: <span class="org-string">"{{ domain_name }}\n"</span>
- /etc/hostname
- /etc/mailname
notify: Update hostname.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">---
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>---
- name: Update hostname.
become: yes
command: hostname -F /etc/hostname
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org053261f" class="outline-3">
-<h3 id="org053261f"><span class="section-number-3">7.3.</span> Add Administrator to System Groups</h3>
+<div id="outline-container-orgc60729b" class="outline-3">
+<h3 id="orgc60729b"><span class="section-number-3">7.3.</span> Add Administrator to System Groups</h3>
<div class="outline-text-3" id="text-7-3">
<p>
The administrator often needs to read (directories of) log files owned
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Add {{ ansible_user }} to system groups.
become: yes
user:
name: <span class="org-string">"{{ ansible_user }}"</span>
append: yes
groups: root,adm
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org633cf3e" class="outline-3">
-<h3 id="org633cf3e"><span class="section-number-3">7.4.</span> Configure SSH</h3>
+<div id="outline-container-org581d004" class="outline-3">
+<h3 id="org581d004"><span class="section-number-3">7.4.</span> Configure SSH</h3>
<div class="outline-text-3" id="text-7-4">
<p>
The SSH service on Front needs to be known to Monkey. The following
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install SSH host keys.
become: yes
copy:
- { name: ssh_host_rsa_key, mode: <span class="org-string">"u=rw,g=,o="</span> }
- { name: ssh_host_rsa_key.pub, mode: <span class="org-string">"u=rw,g=r,o=r"</span> }
notify: Reload SSH server.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Reload SSH server.
become: yes
systemd:
service: ssh
state: reloaded
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orga03d6a3" class="outline-3">
-<h3 id="orga03d6a3"><span class="section-number-3">7.5.</span> Configure Monkey</h3>
+<div id="outline-container-org345d680" class="outline-3">
+<h3 id="org345d680"><span class="section-number-3">7.5.</span> Configure Monkey</h3>
<div class="outline-text-3" id="text-7-5">
<p>
The small institute runs cron jobs and web scripts that generate
system account named <code>monkey</code>. One of Monkey's more important jobs on
Core is to run <code>rsync</code> to update the public web site on Front. Monkey
on Core will login as <code>monkey</code> on Front to synchronize the files (as
-described in <a href="#orgf59dafb">*Configure Apache2</a>). To do that without needing a
+described in <a href="#orgbcda1ce">*Configure Apache2</a>). To do that without needing a
password, the <code>monkey</code> account on Front should authorize Monkey's SSH
key on Core.
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Create monkey.
become: yes
user:
name: <span class="org-string">"{{ ansible_user }}"</span>
append: yes
groups: monkey
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgd1c69a2" class="outline-3">
-<h3 id="orgd1c69a2"><span class="section-number-3">7.6.</span> Install Rsync</h3>
+<div id="outline-container-orgce756fc" class="outline-3">
+<h3 id="orgce756fc"><span class="section-number-3">7.6.</span> Install Rsync</h3>
<div class="outline-text-3" id="text-7-6">
<p>
Monkey uses Rsync to keep the institute's public web site up-to-date.
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install rsync.
become: yes
<span class="org-variable-name">apt: pkg</span>=rsync
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org80f3494" class="outline-3">
-<h3 id="org80f3494"><span class="section-number-3">7.7.</span> Install Unattended Upgrades</h3>
+<div id="outline-container-org0ec2b68" class="outline-3">
+<h3 id="org0ec2b68"><span class="section-number-3">7.7.</span> Install Unattended Upgrades</h3>
<div class="outline-text-3" id="text-7-7">
<p>
The institute prefers to install security updates as soon as possible.
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install basic software.
become: yes
<span class="org-variable-name">apt: pkg</span>=unattended-upgrades
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org07c2e32" class="outline-3">
-<h3 id="org07c2e32"><span class="section-number-3">7.8.</span> Configure User Accounts</h3>
+<div id="outline-container-orgdd1398a" class="outline-3">
+<h3 id="orgdd1398a"><span class="section-number-3">7.8.</span> Configure User Accounts</h3>
<div class="outline-text-3" id="text-7-8">
<p>
User accounts are created immediately so that Postfix and Dovecot can
start delivering email immediately, <i>without</i> returning "no such
-recipient" replies. The <a href="#orge7fe793">Account Management</a> chapter describes the
+recipient" replies. The <a href="#org6138e49">Account Management</a> chapter describes the
<code>members</code> and <code>usernames</code> variables used below.
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Create user accounts.
become: yes
user:
loop: <span class="org-string">"{{ usernames }}"</span>
<span class="org-variable-name">when: members[item].status !</span>= <span class="org-string">'current'</span>
tags: accounts
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org42ffdc5" class="outline-3">
-<h3 id="org42ffdc5"><span class="section-number-3">7.9.</span> Install Server Certificate</h3>
+<div id="outline-container-org7ce2595" class="outline-3">
+<h3 id="org7ce2595"><span class="section-number-3">7.9.</span> Install Server Certificate</h3>
<div class="outline-text-3" id="text-7-9">
<p>
The servers on Front use the same certificate (and key) to
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install server certificate/key.
become: yes
copy:
notify:
- Restart Postfix.
- Restart Dovecot.
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgba341a6" class="outline-3">
-<h3 id="orgba341a6"><span class="section-number-3">7.10.</span> Configure Postfix on Front</h3>
+<div id="outline-container-orga330953" class="outline-3">
+<h3 id="orga330953"><span class="section-number-3">7.10.</span> Configure Postfix on Front</h3>
<div class="outline-text-3" id="text-7-10">
<p>
Front uses Postfix to provide the institute's public SMTP service, and
</ul>
<p>
-As discussed in <a href="#org22a6220">The Email Service</a> above, Front's Postfix configuration
+As discussed in <a href="#org73635f2">The Email Service</a> above, Front's Postfix configuration
includes site-wide support for larger message sizes, shorter queue
times, the relaying configuration, and the common path to incoming
emails. These and a few Front-specific Postfix configurations
</p>
<div class="org-src-container">
-<code>postfix-front-networks</code><pre class="src src-conf" id="org4009fa9">- p: mynetworks
+<code>postfix-front-networks</code><pre class="src src-conf" id="orgba644bd"><code>- p: mynetworks
v: >-
{{ public_vpn_net_cidr }}
127.0.0.0/8
[<span class="org-type">::ffff:127.0.0.0</span>]/104
[<span class="org-type">::1</span>]/128
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-front-restrictions</code><pre class="src src-conf" id="org8c163ac">- p: smtpd_recipient_restrictions
+<code>postfix-front-restrictions</code><pre class="src src-conf" id="orga288f25"><code>- p: smtpd_recipient_restrictions
v: >-
permit_mynetworks
reject_unauth_pipelining
reject_unauth_destination
reject_unknown_sender_domain
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-header-checks</code><pre class="src src-conf" id="org041fc35">- p: smtp_header_checks
+<code>postfix-header-checks</code><pre class="src src-conf" id="orga20329d"><code>- p: smtp_header_checks
v: regexp:/etc/postfix/header_checks.cf
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<code>postfix-header-checks-content</code><pre class="src src-conf" id="org19e49f9">/^Received:/ IGNORE
+<code>postfix-header-checks-content</code><pre class="src src-conf" id="org0057dfe"><code>/^Received:/ IGNORE
/^User-Agent:/ IGNORE
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-front</code><pre class="src src-conf" id="org86d7293">- { p: smtpd_tls_cert_file, v: /etc/server.crt }
+<code>postfix-front</code><pre class="src src-conf" id="org5ee702d"><code>- { p: smtpd_tls_cert_file, v: /etc/server.crt }
- { p: smtpd_tls_key_file, v: /etc/server.key }
<<postfix-front-networks>>
<<postfix-front-restrictions>>
<<postfix-queue-times>>
<<postfix-maildir>>
<<postfix-header-checks>>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Postfix.
become: yes
<span class="org-variable-name">apt: pkg</span>=postfix
service: postfix
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart Postfix.
become: yes
systemd:
chdir: /etc/postfix/
cmd: postmap header_checks.cf
notify: Restart Postfix.
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orge52533b" class="outline-3">
-<h3 id="orge52533b"><span class="section-number-3">7.11.</span> Configure Public Email Aliases</h3>
+<div id="outline-container-org75a0395" class="outline-3">
+<h3 id="org75a0395"><span class="section-number-3">7.11.</span> Configure Public Email Aliases</h3>
<div class="outline-text-3" id="text-7-11">
<p>
The institute's Front needs to deliver email addressed to a number of
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">- name: Install institute email aliases.
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>- name: Install institute email aliases.
become: yes
blockinfile:
block: |
path: /etc/aliases
marker: <span class="org-string">"# {mark} INSTITUTE MANAGED BLOCK"</span>
notify: New aliases.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: New aliases.
become: yes
command: newaliases
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org7960eac" class="outline-3">
-<h3 id="org7960eac"><span class="section-number-3">7.12.</span> Configure Dovecot IMAPd</h3>
+<div id="outline-container-orgdc00207" class="outline-3">
+<h3 id="orgdc00207"><span class="section-number-3">7.12.</span> Configure Dovecot IMAPd</h3>
<div class="outline-text-3" id="text-7-12">
<p>
Front uses Dovecot's IMAPd to allow user Fetchmail jobs on Core to
bit "over the top" given that Core accesses Front via VPN, but helps
to ensure privacy even when members must, in extremis, access recent
email directly from their accounts on Front. For more information
-about Front's role in the institute's email services, see <a href="#org22a6220">The Email
+about Front's role in the institute's email services, see <a href="#org73635f2">The Email
Service</a>.
</p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Dovecot IMAPd.
become: yes
<span class="org-variable-name">apt: pkg</span>=dovecot-imapd
service: dovecot
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart Dovecot.
become: yes
systemd:
service: dovecot
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgae570f4" class="outline-3">
-<h3 id="orgae570f4"><span class="section-number-3">7.13.</span> Configure Apache2 <a id="orgf59dafb"></a></h3>
+<div id="outline-container-orga7d4870" class="outline-3">
+<h3 id="orga7d4870"><span class="section-number-3">7.13.</span> Configure Apache2 <a id="orgbcda1ce"></a></h3>
<div class="outline-text-3" id="text-7-13">
<p>
This is the small institute's public web site. It is simple, static,
</p>
<div class="org-src-container">
-<code>apache-ciphers</code><pre class="src src-conf" id="orgd788462">SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
+<code>apache-ciphers</code><pre class="src src-conf" id="orgd32683d"><code>SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder on
<span class="org-type">SSLCipherSuite {</span>{ [ <span class="org-string">'ECDHE-ECDSA-AES128-GCM-SHA256'</span>,
<span class="org-string">'ECDHE-ECDSA-AES256-GCM-SHA384'</span>,
<span class="org-string">'!SRP'</span>,
<span class="org-string">'!DSS'</span>,
<span class="org-string">'!RC4'</span> ] |join(<span class="org-string">":"</span>) }}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>apache-userdir-front</code><pre class="src src-conf" id="org02137da">UserDir /home/www-users
+<code>apache-userdir-front</code><pre class="src src-conf" id="org5949197"><code>UserDir /home/www-users
<Directory /home/www-users/>
Require all granted
AllowOverride None
</Directory>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>apache-redirect-front</code><pre class="src src-conf" id="org77c4862"><VirtualHost *:80>
+<code>apache-redirect-front</code><pre class="src src-conf" id="org8203d34"><code><VirtualHost *:80>
Redirect permanent / https://{{ domain_name }}/
</VirtualHost>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>apache-front</code><pre class="src src-conf" id="org303a264">ServerName {{ domain_name }}
+<code>apache-front</code><pre class="src src-conf" id="org26265cf"><code>ServerName {{ domain_name }}
ServerAdmin webmaster@{{ domain_name }}
DocumentRoot /home/www
</VirtualHost>
<<apache-ciphers>>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Apache2.
become: yes
<span class="org-variable-name">apt: pkg</span>=apache2
service: apache2
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart Apache2.
become: yes
systemd:
service: apache2
state: restarted
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Disable default vhosts.
become: yes
file:
state: absent
loop: [ 000-default.conf, default-ssl.conf ]
notify: Restart Apache2.
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Disable other-vhosts-access-log option.
become: yes
file:
path: /etc/apache2/conf-enabled/other-vhosts-access-log.conf
state: absent
notify: Restart Apache2.
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Create UserDir.
become: yes
file:
loop: <span class="org-string">"{{ usernames }}"</span>
<span class="org-variable-name">when: members[item].status !</span>= <span class="org-string">'current'</span>
tags: accounts
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org24ac22d" class="outline-3">
-<h3 id="org24ac22d"><span class="section-number-3">7.14.</span> Configure OpenVPN</h3>
+<div id="outline-container-org3bc00f9" class="outline-3">
+<h3 id="org3bc00f9"><span class="section-number-3">7.14.</span> Configure OpenVPN</h3>
<div class="outline-text-3" id="text-7-14">
<p>
Front uses OpenVPN to provide the institute's public VPN service. The
</p>
<div class="org-src-container">
-<code>openvpn-ccd-core</code><pre class="src src-conf" id="orge20d97e">iroute {{ private_net_and_mask }}
+<code>openvpn-ccd-core</code><pre class="src src-conf" id="orgbbdd4f4"><code>iroute {{ private_net_and_mask }}
iroute {{ campus_vpn_net_and_mask }}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>openvpn-front-routes</code><pre class="src src-conf" id="org2a2ea3d">route {{ private_net_and_mask }}
+<code>openvpn-front-routes</code><pre class="src src-conf" id="org9e2d873"><code>route {{ private_net_and_mask }}
route {{ campus_vpn_net_and_mask }}
push <span class="org-string">"route {{ private_net_and_mask }}"</span>
push <span class="org-string">"route {{ campus_vpn_net_and_mask }}"</span>
-</pre>
+</code></pre>
</div>
<p>
The complete OpenVPN configuration for Front includes a <code>server</code>
option, the <code>client-config-dir</code> option, the routes mentioned above,
-and the common options discussed in <a href="#orgc2baf19">The VPN Service</a>.
+and the common options discussed in <a href="#org1ea6412">The VPN Service</a>.
</p>
<div class="org-src-container">
-<code>openvpn-front</code><pre class="src src-conf" id="orgc467eda">server {{ public_vpn_net_and_mask }}
+<code>openvpn-front</code><pre class="src src-conf" id="org069808e"><code>server {{ public_vpn_net_and_mask }}
client-config-dir /etc/openvpn/ccd
<<openvpn-front-routes>>
<<openvpn-dev-mode>>
cert server.crt
key server.key
dh dh2048.pem
-tls-auth ta.key 0
-</pre>
+tls-crypt shared.key
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install OpenVPN.
become: yes
<span class="org-variable-name">apt: pkg</span>=openvpn
<span class="org-variable-name">mode: u</span>=r,g=,o=
loop:
- { src: front-dh2048.pem, dest: dh2048.pem }
- - { src: front-ta.key, dest: ta.key }
+ - { src: front-shared.key, dest: shared.key }
notify: Restart OpenVPN.
- name: Configure OpenVPN.
service: openvpn@server
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart OpenVPN.
become: yes
systemd:
service: openvpn@server
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgc93df1f" class="outline-3">
-<h3 id="orgc93df1f"><span class="section-number-3">7.15.</span> Configure Kamailio</h3>
+<div id="outline-container-org4ec56d2" class="outline-3">
+<h3 id="org4ec56d2"><span class="section-number-3">7.15.</span> Configure Kamailio</h3>
<div class="outline-text-3" id="text-7-15">
<p>
Front uses Kamailio to provide a SIP service on the public VPN so that
</p>
<div class="org-src-container">
-<code>kamailio</code><pre class="src src-conf" id="org3b9039b"><span class="org-variable-name">listen</span>=udp:{{ front_private_addr }}:5060
-</pre>
+<code>kamailio</code><pre class="src src-conf" id="orga8e875c"><code><span class="org-variable-name">listen</span>=udp:{{ front_private_addr }}:5060
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Kamailio.
become: yes
<span class="org-variable-name">apt: pkg</span>=kamailio
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Create Kamailio/Systemd configuration drop.
become: yes
file:
<span class="org-variable-name">After</span>=sys-devices-virtual-net-ovpn.device
dest: /etc/systemd/system/kamailio.service.d/depend.conf
notify: Reload Systemd.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Reload Systemd.
become: yes
systemd:
daemon-reload: yes
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/tasks/main.yml"><q>roles_t/front/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure Kamailio.
become: yes
copy:
service: kamailio
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/front/handlers/main.yml"><q>roles_t/front/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart Kamailio.
become: yes
systemd:
service: kamailio
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-orge7ebc83" class="outline-2">
-<h2 id="orge7ebc83"><span class="section-number-2">8.</span> The Core Role</h2>
+<div id="outline-container-orge6d718e" class="outline-2">
+<h2 id="orge6d718e"><span class="section-number-2">8.</span> The Core Role</h2>
<div class="outline-text-2" id="text-8">
<p>
The <code>core</code> role configures many essential campus network services as
well as the institute's private cloud, so the core machine has
horsepower (CPUs and RAM) and large disks and is prepared with a
Debian install and remote access to a privileged, administrator's
-account. (For details, see <a href="#org8d60b7b">The Core Machine</a>.)
+account. (For details, see <a href="#orgae4ce75">The Core Machine</a>.)
</p>
</div>
-<div id="outline-container-orgca8f5da" class="outline-3">
-<h3 id="orgca8f5da"><span class="section-number-3">8.1.</span> Include Particulars</h3>
+<div id="outline-container-org9f10251" class="outline-3">
+<h3 id="org9f10251"><span class="section-number-3">8.1.</span> Include Particulars</h3>
<div class="outline-text-3" id="text-8-1">
<p>
-The first task, as in <a href="#org9240129">The Front Role</a>, is to include the institute
+The first task, as in <a href="#org1024107">The Front Role</a>, is to include the institute
particulars and membership roll.
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">---
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>---
- name: Include public variables.
include_vars: ../public/vars.yml
tags: accounts
- name: Include members.
include_vars: <span class="org-string">"{{ lookup('first_found', membership_rolls) }}"</span>
tags: accounts
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org90da685" class="outline-3">
-<h3 id="org90da685"><span class="section-number-3">8.2.</span> Configure Hostname</h3>
+<div id="outline-container-orgf5285f9" class="outline-3">
+<h3 id="orgf5285f9"><span class="section-number-3">8.2.</span> Configure Hostname</h3>
<div class="outline-text-3" id="text-8-2">
<p>
This task ensures that Core's <q>/etc/hostname</q> and <q>/etc/mailname</q> are
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure hostname.
become: yes
copy:
- { name: <span class="org-string">"core.{{ domain_priv }}"</span>, file: /etc/mailname }
- { name: <span class="org-string">"{{ inventory_hostname }}"</span>, file: /etc/hostname }
notify: Update hostname.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">---
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>---
- name: Update hostname.
become: yes
command: hostname -F /etc/hostname
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org0fa3ade" class="outline-3">
-<h3 id="org0fa3ade"><span class="section-number-3">8.3.</span> Configure Systemd Resolved</h3>
+<div id="outline-container-org06a86c3" class="outline-3">
+<h3 id="org06a86c3"><span class="section-number-3">8.3.</span> Configure Systemd Resolved</h3>
<div class="outline-text-3" id="text-8-3">
<p>
Core runs the campus name server, so Resolved is configured to use it
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure resolved.
become: yes
lineinfile:
notify:
- Reload Systemd.
- Restart Systemd resolved.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Reload Systemd.
become: yes
systemd:
systemd:
service: systemd-resolved
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org2dec986" class="outline-3">
-<h3 id="org2dec986"><span class="section-number-3">8.4.</span> Configure Netplan</h3>
+<div id="outline-container-org9272d80" class="outline-3">
+<h3 id="org9272d80"><span class="section-number-3">8.4.</span> Configure Netplan</h3>
<div class="outline-text-3" id="text-8-4">
<p>
Core's network interface is statically configured using Netplan and an
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">core_ethernet: enp0s3
-</pre>
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>core_ethernet: enp0s3
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install netplan.
become: yes
<span class="org-variable-name">apt: pkg</span>=netplan.io
dest: /etc/netplan/60-core.yaml
<span class="org-variable-name">mode: u</span>=rw,g=r,o=
notify: Apply netplan.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Apply netplan.
become: yes
command: netplan apply
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org404665f" class="outline-3">
-<h3 id="org404665f"><span class="section-number-3">8.5.</span> Configure DHCP For the Private Ethernet</h3>
+<div id="outline-container-orgf1c124e" class="outline-3">
+<h3 id="orgf1c124e"><span class="section-number-3">8.5.</span> Configure DHCP For the Private Ethernet</h3>
<div class="outline-text-3" id="text-8-5">
<p>
Core speaks DHCP (Dynamic Host Configuration Protocol) using the
RFC3442's extension to encode a second (non-default) static route.
The default route is through the campus ISP at Gate. A second route
directs campus traffic to the Front VPN through Core. This is just an
-example file. The administrator adds and removes actual machines from
-the actual <a href="private/core-dhcpd.conf"><q>private/core-dhcpd.conf</q></a> file.
+example file, with MAC addresses chosen to (probably?) match
+VirtualBox test machines. In actual use <q>private/core-dhcpd.conf</q>
+refers to a replacement file.
</p>
<div class="org-src-container">
-<a href="private/core-dhcpd.conf"><q>private/core-dhcpd.conf</q></a><pre class="src src-conf">option domain-name <span class="org-string">"small.private"</span>;
+<a href="private/core-dhcpd.conf"><q>private/core-dhcpd.conf</q></a><pre class="src src-conf"><code>option domain-name <span class="org-string">"small.private"</span>;
option domain-name-servers 192.168.56.1;
default-lease-time 3600;
hardware ethernet 08:00:27:e0:79:ab; fixed-address 192.168.56.2; }
<span class="org-type">host server</span> {
hardware ethernet 08:00:27:f3:41:66; fixed-address 192.168.56.3; }
-</pre>
+</code></pre>
</div>
<p>
-The following tasks install the ISC's DHCP server and configure it
-with the real <a href="private/core-dhcpd.conf"><q>private/core-dhcpd.conf</q></a> (<i>not</i> the example above).
+The following tasks install ISC's DHCP server and configure it with
+the real <a href="private/core-dhcpd.conf"><q>private/core-dhcpd.conf</q></a> (<i>not</i> the example above).
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install DHCP server.
become: yes
<span class="org-variable-name">apt: pkg</span>=isc-dhcp-server
service: isc-dhcp-server
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart DHCP server.
become: yes
systemd:
service: isc-dhcp-server
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org2134214" class="outline-3">
-<h3 id="org2134214"><span class="section-number-3">8.6.</span> Configure BIND9</h3>
+<div id="outline-container-org40752b1" class="outline-3">
+<h3 id="org40752b1"><span class="section-number-3">8.6.</span> Configure BIND9</h3>
<div class="outline-text-3" id="text-8-6">
<p>
Core uses BIND9 to provide name service for the institute as described
-in <a href="#org12ea1d0">The Name Service</a>. The configuration supports reverse name lookups,
+in <a href="#org189ccc3">The Name Service</a>. The configuration supports reverse name lookups,
resolving many private network addresses to private domain names.
</p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install BIND9.
become: yes
<span class="org-variable-name">apt: pkg</span>=bind9
service: bind9
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Reload BIND9.
become: yes
systemd:
service: bind9
state: reloaded
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>bind-options</code><pre class="src src-conf" id="orgd750f78"><span class="org-type">acl </span><span class="org-string"><span class="org-type">"trusted"</span></span> {
+<code>bind-options</code><pre class="src src-conf" id="orgaf3e96b"><code><span class="org-type">acl </span><span class="org-string"><span class="org-type">"trusted"</span></span> {
{{ private_net_cidr }};
+ {{ wild_net_cidr }};
{{ public_vpn_net_cidr }};
{{ campus_vpn_net_cidr }};
- {{ gate_wifi_net_cidr }};
localhost;
};
localhost;
};
};
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<code>bind-local</code><pre class="src src-conf" id="orge2f865d">include <span class="org-string">"/etc/bind/zones.rfc1918"</span>;
+<code>bind-local</code><pre class="src src-conf" id="org5ab6230"><code>include <span class="org-string">"/etc/bind/zones.rfc1918"</span>;
<span class="org-type">zone </span><span class="org-string"><span class="org-type">"{{ domain_priv }}."</span></span> {
type master;
type master;
file <span class="org-string">"/etc/bind/db.campus_vpn"</span>;
};
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="private/db.domain"><q>private/db.domain</q></a><pre class="src src-conf">;
+<a href="private/db.domain"><q>private/db.domain</q></a><pre class="src src-conf"><code>;
; BIND data file for a small institute<span class="org-string">'s PRIVATE domain names.</span>
<span class="org-string">;</span>
<span class="org-string">$TTL 604800</span>
<span class="org-string">;</span>
<span class="org-string">core IN A 192.168.56.1</span>
<span class="org-string">gate IN A 192.168.56.2</span>
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="private/db.private"><q>private/db.private</q></a><pre class="src src-conf">;
+<a href="private/db.private"><q>private/db.private</q></a><pre class="src src-conf"><code>;
; BIND reverse data file for a small institute<span class="org-string">'s private Ethernet.</span>
<span class="org-string">;</span>
<span class="org-string">$TTL 604800</span>
<span class="org-string">$TTL 7200</span>
<span class="org-string">1 IN PTR core.small.private.</span>
<span class="org-string">2 IN PTR gate.small.private.</span>
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="private/db.public_vpn"><q>private/db.public_vpn</q></a><pre class="src src-conf">;
+<a href="private/db.public_vpn"><q>private/db.public_vpn</q></a><pre class="src src-conf"><code>;
; BIND reverse data file for a small institute<span class="org-string">'s public VPN.</span>
<span class="org-string">;</span>
<span class="org-string">$TTL 604800</span>
<span class="org-string">$TTL 7200</span>
<span class="org-string">1 IN PTR front-p.small.private.</span>
<span class="org-string">2 IN PTR core-p.small.private.</span>
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="private/db.campus_vpn"><q>private/db.campus_vpn</q></a><pre class="src src-conf">;
+<a href="private/db.campus_vpn"><q>private/db.campus_vpn</q></a><pre class="src src-conf"><code>;
; BIND reverse data file for a small institute<span class="org-string">'s campus VPN.</span>
<span class="org-string">;</span>
<span class="org-string">$TTL 604800</span>
<span class="org-string">@ IN NS core.small.private.</span>
<span class="org-string">$TTL 7200</span>
<span class="org-string">1 IN PTR gate-c.small.private.</span>
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgb5d04d3" class="outline-3">
-<h3 id="orgb5d04d3"><span class="section-number-3">8.7.</span> Add Administrator to System Groups</h3>
+<div id="outline-container-org7b737c7" class="outline-3">
+<h3 id="org7b737c7"><span class="section-number-3">8.7.</span> Add Administrator to System Groups</h3>
<div class="outline-text-3" id="text-8-7">
<p>
The administrator often needs to read (directories of) log files owned
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Add {{ ansible_user }} to system groups.
become: yes
user:
name: <span class="org-string">"{{ ansible_user }}"</span>
append: yes
groups: root,adm
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org6f07952" class="outline-3">
-<h3 id="org6f07952"><span class="section-number-3">8.8.</span> Configure Monkey</h3>
+<div id="outline-container-orgd39c2c0" class="outline-3">
+<h3 id="orgd39c2c0"><span class="section-number-3">8.8.</span> Configure Monkey</h3>
<div class="outline-text-3" id="text-8-8">
<p>
The small institute runs cron jobs and web scripts that generate
reports and perform checks. The un-privileged jobs are run by a
system account named <code>monkey</code>. One of Monkey's more important jobs on
Core is to run <code>rsync</code> to update the public web site on Front (as
-described in <a href="#org1ac6235">*Configure Apache2</a>).
+described in <a href="#org682dcfc">*Configure Apache2</a>).
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Create monkey.
become: yes
user:
owner: monkey
group: monkey
mode: <span class="org-string">"u=rw,g=,o="</span>
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org3a924c4" class="outline-3">
-<h3 id="org3a924c4"><span class="section-number-3">8.9.</span> Install Unattended Upgrades</h3>
+<div id="outline-container-orgb3bf17a" class="outline-3">
+<h3 id="orgb3bf17a"><span class="section-number-3">8.9.</span> Install Unattended Upgrades</h3>
<div class="outline-text-3" id="text-8-9">
<p>
The institute prefers to install security updates as soon as possible.
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install basic software.
become: yes
<span class="org-variable-name">apt: pkg</span>=unattended-upgrades
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgd919e4d" class="outline-3">
-<h3 id="orgd919e4d"><span class="section-number-3">8.10.</span> Install Expect</h3>
+<div id="outline-container-org9e31a35" class="outline-3">
+<h3 id="org9e31a35"><span class="section-number-3">8.10.</span> Install Expect</h3>
<div class="outline-text-3" id="text-8-10">
<p>
-The <code>expect</code> program is used by <a href="#org1c6f4a8">The Institute Commands</a> to interact
+The <code>expect</code> program is used by <a href="#org5db480b">The Institute Commands</a> to interact
with Nextcloud on the command line.
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install expect.
become: yes
<span class="org-variable-name">apt: pkg</span>=expect
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org2e19b28" class="outline-3">
-<h3 id="org2e19b28"><span class="section-number-3">8.11.</span> Configure User Accounts</h3>
+<div id="outline-container-org2d28846" class="outline-3">
+<h3 id="org2d28846"><span class="section-number-3">8.11.</span> Configure User Accounts</h3>
<div class="outline-text-3" id="text-8-11">
<p>
User accounts are created immediately so that backups can begin
-restoring as soon as possible. The <a href="#orge7fe793">Account Management</a> chapter
+restoring as soon as possible. The <a href="#org6138e49">Account Management</a> chapter
describes the <code>members</code> and <code>usernames</code> variables.
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Create user accounts.
become: yes
user:
loop: <span class="org-string">"{{ usernames }}"</span>
<span class="org-variable-name">when: members[item].status !</span>= <span class="org-string">'current'</span>
tags: accounts
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org3893d2e" class="outline-3">
-<h3 id="org3893d2e"><span class="section-number-3">8.12.</span> Install Server Certificate</h3>
+<div id="outline-container-org3c35b95" class="outline-3">
+<h3 id="org3c35b95"><span class="section-number-3">8.12.</span> Install Server Certificate</h3>
<div class="outline-text-3" id="text-8-12">
<p>
The servers on Core use the same certificate (and key) to authenticate
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install server certificate/key.
become: yes
copy:
- Restart Postfix.
- Restart Dovecot.
- Restart OpenVPN.
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org1a74046" class="outline-3">
-<h3 id="org1a74046"><span class="section-number-3">8.13.</span> Install NTP</h3>
+<div id="outline-container-org668ece0" class="outline-3">
+<h3 id="org668ece0"><span class="section-number-3">8.13.</span> Install NTP</h3>
<div class="outline-text-3" id="text-8-13">
<p>
Core uses NTP to provide a time synchronization service to the campus.
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install NTP.
become: yes
<span class="org-variable-name">apt: pkg</span>=ntp
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org948efaa" class="outline-3">
-<h3 id="org948efaa"><span class="section-number-3">8.14.</span> Configure Postfix on Core</h3>
+<div id="outline-container-org296b053" class="outline-3">
+<h3 id="org296b053"><span class="section-number-3">8.14.</span> Configure Postfix on Core</h3>
<div class="outline-text-3" id="text-8-14">
<p>
Core uses Postfix to provide SMTP service to the campus. The default
</ul>
<p>
-As discussed in <a href="#org22a6220">The Email Service</a> above, Core delivers email addressed
+As discussed in <a href="#org73635f2">The Email Service</a> above, Core delivers email addressed
to any internal domain name locally, and uses its smarthost Front to
relay the rest. Core is reachable only on institute networks, so
there is little benefit in enabling TLS, but it does need to handle
</p>
<div class="org-src-container">
-<code>postfix-core-networks</code><pre class="src src-conf" id="orgf232831">- p: mynetworks
+<code>postfix-core-networks</code><pre class="src src-conf" id="org24ddb59"><code>- p: mynetworks
v: >-
{{ private_net_cidr }}
{{ public_vpn_net_cidr }}
127.0.0.0/8
[<span class="org-type">::ffff:127.0.0.0</span>]/104
[<span class="org-type">::1</span>]/128
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-core-relayhost</code><pre class="src src-conf" id="org4eda440">- { p: relayhost, v: <span class="org-string">"[{{ front_private_addr }}]"</span> }
-</pre>
+<code>postfix-core-relayhost</code><pre class="src src-conf" id="orgabfee7f"><code>- { p: relayhost, v: <span class="org-string">"[{{ front_private_addr }}]"</span> }
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-transport</code><pre class="src src-conf" id="org32b43ff">.{{ domain_name }} local:$myhostname
+<code>postfix-transport</code><pre class="src src-conf" id="org7dc82f6"><code>.{{ domain_name }} local:$myhostname
.{{ domain_priv }} local:$myhostname
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>postfix-core</code><pre class="src src-conf" id="org4ccefef"><<postfix-relaying>>
+<code>postfix-core</code><pre class="src src-conf" id="org7e631cc"><code><<postfix-relaying>>
- { p: smtpd_tls_security_level, v: none }
- { p: smtp_tls_security_level, v: none }
<<postfix-message-size>>
<<postfix-core-networks>>
<<postfix-core-relayhost>>
- { p: inet_interfaces, v: <span class="org-string">"127.0.0.1 {{ core_addr }}"</span> }
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Postfix.
become: yes
<span class="org-variable-name">apt: pkg</span>=postfix
service: postfix
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart Postfix.
become: yes
systemd:
chdir: /etc/postfix/
cmd: postmap transport
notify: Restart Postfix.
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgaf844fe" class="outline-3">
-<h3 id="orgaf844fe"><span class="section-number-3">8.15.</span> Configure Private Email Aliases</h3>
+<div id="outline-container-org8d9476a" class="outline-3">
+<h3 id="org8d9476a"><span class="section-number-3">8.15.</span> Configure Private Email Aliases</h3>
<div class="outline-text-3" id="text-8-15">
<p>
The institute's Core needs to deliver email addressed to institute
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install institute email aliases.
become: yes
blockinfile:
path: /etc/aliases
marker: <span class="org-string">"# {mark} INSTITUTE MANAGED BLOCK"</span>
notify: New aliases.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: New aliases.
become: yes
command: newaliases
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org14b48ba" class="outline-3">
-<h3 id="org14b48ba"><span class="section-number-3">8.16.</span> Configure Dovecot IMAPd</h3>
+<div id="outline-container-org77e47c0" class="outline-3">
+<h3 id="org77e47c0"><span class="section-number-3">8.16.</span> Configure Dovecot IMAPd</h3>
<div class="outline-text-3" id="text-8-16">
<p>
Core uses Dovecot's IMAPd to store and serve member emails. As on
networks, but helps to ensure privacy even when members accidentally
attempt connections from outside the private networks. For more
information about Core's role in the institute's email services, see
-<a href="#org22a6220">The Email Service</a>.
+<a href="#org73635f2">The Email Service</a>.
</p>
<p>
<q>README.Debian</q> (in <q>/usr/share/dovecot-core/</q>) but replaces the
default "snake oil" certificate with another, signed by the institute.
(For more information about the institute's X.509 certificates, see
-<a href="#org6519b0c">Keys</a>.)
+<a href="#org1c1be46">Keys</a>.)
</p>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Dovecot IMAPd.
become: yes
<span class="org-variable-name">apt: pkg</span>=dovecot-imapd
service: dovecot
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart Dovecot.
become: yes
systemd:
service: dovecot
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org5a3cd75" class="outline-3">
-<h3 id="org5a3cd75"><span class="section-number-3">8.17.</span> Configure Fetchmail</h3>
+<div id="outline-container-orgea0cf88" class="outline-3">
+<h3 id="orgea0cf88"><span class="section-number-3">8.17.</span> Configure Fetchmail</h3>
<div class="outline-text-3" id="text-8-17">
<p>
Core runs a <code>fetchmail</code> for each member of the institute. Individual
</p>
<div class="org-src-container">
-<code>fetchmail-config</code><pre class="src src-conf" id="orgfa39704"><span class="org-comment-delimiter"># </span><span class="org-comment">Permissions on this file may be no greater than 0600.</span>
+<code>fetchmail-config</code><pre class="src src-conf" id="orge18ab2e"><code><span class="org-comment-delimiter"># </span><span class="org-comment">Permissions on this file may be no greater than 0600.</span>
set no bouncemail
set no spambounce
username {{ item }}
password <span class="org-string">"{{ members[item].password_fetchmail }}"</span> fetchall
ssl sslproto tls1.2+ sslcertck sslcommonname {{ domain_name }}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>fetchmail-service</code><pre class="src src-conf" id="org712bd17">[<span class="org-type">Unit</span>]
+<code>fetchmail-service</code><pre class="src src-conf" id="orga4027c9"><code>[<span class="org-type">Unit</span>]
<span class="org-variable-name">Description</span>=Fetchmail --idle task for {{ item }}.
<span class="org-variable-name">AssertPathExists</span>=/home/{{ item }}/.fetchmailrc
<span class="org-variable-name">After</span>=openvpn@front.service
[<span class="org-type">Install</span>]
<span class="org-variable-name">WantedBy</span>=default.target
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install fetchmail.
become: yes
<span class="org-variable-name">apt: pkg</span>=fetchmail
<span class="org-variable-name">- members[item].status</span> == <span class="org-string">'current'</span>
- members[item].password_fetchmail is defined
tags: accounts
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Stop former user fetchmail services.
become: yes
systemd:
<span class="org-variable-name">- members[item].status !</span>= <span class="org-string">'current'</span>
- members[item].password_fetchmail is defined
tags: accounts
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-conf">
+<pre class="src src-conf"><code>
- name: Delete former user fetchmail services.
become: yes
file:
<span class="org-variable-name">- members[item].status !</span>= <span class="org-string">'current'</span>
- members[item].password_fetchmail is defined
tags: accounts
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org14de2c2" class="outline-3">
-<h3 id="org14de2c2"><span class="section-number-3">8.18.</span> Configure Apache2 <a id="org1ac6235"></a></h3>
+<div id="outline-container-orgbdf8137" class="outline-3">
+<h3 id="orgbdf8137"><span class="section-number-3">8.18.</span> Configure Apache2 <a id="org682dcfc"></a></h3>
<div class="outline-text-3" id="text-8-18">
<p>
This is the small institute's campus web server. It hosts several web
-sites as described in <a href="#org43cbe17">The Web Services</a>.
+sites as described in <a href="#orgf659a90">The Web Services</a>.
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
</p>
<div class="org-src-container">
-<code>apache-userdir-core</code><pre class="src src-conf" id="org74593c4">UserDir Public/HTML
+<code>apache-userdir-core</code><pre class="src src-conf" id="orge344fe6"><code>UserDir Public/HTML
<Directory /home/*/Public/HTML/>
Require all granted
AllowOverride None
</Directory>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>apache-live</code><pre class="src src-conf" id="org59c4779"><VirtualHost *:80>
+<code>apache-live</code><pre class="src src-conf" id="org6306943"><code><VirtualHost *:80>
ServerName live
ServerAlias live.{{ domain_priv }}
ServerAdmin webmaster@core.{{ domain_priv }}
IncludeOptional /etc/apache2/sites-available/live-vhost.conf
</VirtualHost>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>apache-test</code><pre class="src src-conf" id="orgb260f70"><VirtualHost *:80>
+<code>apache-test</code><pre class="src src-conf" id="org455bb19"><code><VirtualHost *:80>
ServerName test
ServerAlias test.{{ domain_priv }}
ServerAdmin webmaster@core.{{ domain_priv }}
IncludeOptional /etc/apache2/sites-available/test-vhost.conf
</VirtualHost>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<code>apache-campus</code><pre class="src src-conf" id="orgeec93c4"><VirtualHost *:80>
+<code>apache-campus</code><pre class="src src-conf" id="org474a92e"><code><VirtualHost *:80>
ServerName www
ServerAlias www.{{ domain_priv }}
ServerAdmin webmaster@core.{{ domain_priv }}
IncludeOptional /etc/apache2/sites-available/www-vhost.conf
</VirtualHost>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Apache2.
become: yes
<span class="org-variable-name">apt: pkg</span>=apache2
become: yes
apache2_module:
name: <span class="org-string">"{{ item }}"</span>
- loop: [ userdir, cgid ]
+ loop: [ userdir, cgid, ssl ]
notify: Restart Apache2.
-</pre>
+
+- name: Configure Apache2 SSL certificate.
+ become: yes
+ lineinfile:
+ path: /etc/apache2/sites-available/default-ssl.conf
+ regexp: <span class="org-string">"^([\t ]*){{ item.p }}"</span>
+ line: <span class="org-string">"\\1{{ item.p }}\t{{ item.v }}"</span>
+ backrefs: yes
+ loop:
+ - { p: SSLCertificateFile, v: <span class="org-string">"/etc/server.crt"</span> }
+ - { p: SSLCertificateKeyFile, v: <span class="org-string">"/etc/server.key"</span> }
+ notify: Restart Apache2.
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install live web site.
become: yes
copy:
command:
cmd: a2ensite -q {{ item }}
creates: /etc/apache2/sites-enabled/{{ item }}.conf
- loop: [ live, test, www ]
+ loop: [ live, test, www, default-ssl ]
notify: Restart Apache2.
- name: Enable/Start Apache2.
service: apache2
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart Apache2.
become: yes
systemd:
service: apache2
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org5eefe23" class="outline-3">
-<h3 id="org5eefe23"><span class="section-number-3">8.19.</span> Configure Website Updates</h3>
+<div id="outline-container-org88cbb1f" class="outline-3">
+<h3 id="org88cbb1f"><span class="section-number-3">8.19.</span> Configure Website Updates</h3>
<div class="outline-text-3" id="text-8-19">
<p>
Monkey on Core runs <q>/usr/local/sbin/webupdate</q> every 15 minutes via a
</p>
<div class="org-src-container">
-<a href="private/webupdate"><q>private/webupdate</q></a><pre class="src src-sh" id="orgbb22232"><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">bash</span><span class="org-comment"> -e</span>
+<a href="private/webupdate"><q>private/webupdate</q></a><pre class="src src-sh" id="org56430fc"><code><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">bash</span><span class="org-comment"> -e</span>
<span class="org-comment-delimiter">#</span>
<span class="org-comment-delimiter"># </span><span class="org-comment">DO NOT EDIT. This file was tangled from institute.org.</span>
--filter=<span class="org-string">'exclude *~'</span> <span class="org-sh-escaped-newline">\</span>
--filter=<span class="org-string">'exclude .git*'</span> <span class="org-sh-escaped-newline">\</span>
./ {{ domain_name }}:/home/www/
-</pre>
+</code></pre>
</div>
<p>
The following tasks install the <q>webupdate</q> script from <a href="private/"><q>private/</q></a>,
and create Monkey's <code>cron</code> job. An example <q>webupdate</q> script is
-provided <a href="#orgbb22232">here</a>.
+provided <a href="#org56430fc">here</a>.
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: <span class="org-string">"Install Monkey's webupdate script."</span>
become: yes
copy:
job: <span class="org-string">"[ -d /WWW/live ] && /usr/local/sbin/webupdate"</span>
name: webupdate
user: monkey
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org0eac7f7" class="outline-3">
-<h3 id="org0eac7f7"><span class="section-number-3">8.20.</span> Configure OpenVPN Connection to Front</h3>
+<div id="outline-container-org31f8027" class="outline-3">
+<h3 id="org31f8027"><span class="section-number-3">8.20.</span> Configure OpenVPN Connection to Front</h3>
<div class="outline-text-3" id="text-8-20">
<p>
Core connects to Front's public VPN to provide members abroad with a
</p>
<div class="org-src-container">
-<code>openvpn-core</code><pre class="src src-conf" id="orgffe384f">client
+<code>openvpn-core</code><pre class="src src-conf" id="org7db87cf"><code>client
dev-type tun
dev ovpn
remote {{ front_addr }}
ca /usr/local/share/ca-certificates/{{ domain_name }}.crt
cert client.crt
key client.key
-tls-auth ta.key 1
-</pre>
+tls-crypt shared.key
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install OpenVPN.
become: yes
<span class="org-variable-name">apt: pkg</span>=openvpn
- name: Install OpenVPN secret.
become: yes
copy:
- src: ../Secret/front-ta.key
- dest: /etc/openvpn/ta.key
+ src: ../Secret/front-shared.key
+ dest: /etc/openvpn/shared.key
<span class="org-variable-name">mode: u</span>=r,g=,o=
notify: Restart OpenVPN.
service: openvpn@front
state: started
enabled: yes
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart OpenVPN.
become: yes
systemd:
service: openvpn@front
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org517dee3" class="outline-3">
-<h3 id="org517dee3"><span class="section-number-3">8.21.</span> Configure NAGIOS</h3>
+<div id="outline-container-org6cb627e" class="outline-3">
+<h3 id="org6cb627e"><span class="section-number-3">8.21.</span> Configure NAGIOS</h3>
<div class="outline-text-3" id="text-8-21">
<p>
Core runs a <code>nagios4</code> server to monitor "services" on institute hosts.
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install NAGIOS4.
become: yes
apt:
service: nagios4
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Reload NAGIOS4.
become: yes
systemd:
service: nagios4
state: reloaded
-</pre>
+</code></pre>
</div>
</div>
-<div id="outline-container-orgda831f7" class="outline-4">
-<h4 id="orgda831f7"><span class="section-number-4">8.21.1.</span> Configure NAGIOS Monitors for Core</h4>
+<div id="outline-container-org74a0c8d" class="outline-4">
+<h4 id="org74a0c8d"><span class="section-number-4">8.21.1.</span> Configure NAGIOS Monitors for Core</h4>
<div class="outline-text-4" id="text-8-21-1">
<p>
The first block in <q>nagios.cfg</q> specifies monitors for services on
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><span class="org-type">define host</span> {
+<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><code><span class="org-type">define host</span> {
use linux-server
host_name core
address 127.0.0.1
service_description HTTP
check_command check_http
}
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org447bb4c" class="outline-4">
-<h4 id="org447bb4c"><span class="section-number-4">8.21.2.</span> Custom NAGIOS Monitor <code>inst_sensors</code></h4>
+<div id="outline-container-orgb9ed6e7" class="outline-4">
+<h4 id="orgb9ed6e7"><span class="section-number-4">8.21.2.</span> Custom NAGIOS Monitor <code>inst_sensors</code></h4>
<div class="outline-text-4" id="text-8-21-2">
<p>
The <code>check_sensors</code> plugin is included in the package
</p>
<div class="org-src-container">
-<a href="roles_t/core/files/inst_sensors"><q>roles_t/core/files/inst_sensors</q></a><pre class="src src-sh"><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">sh</span>
+<a href="roles_t/core/files/inst_sensors"><q>roles_t/core/files/inst_sensors</q></a><pre class="src src-sh"><code><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">sh</span>
<span class="org-variable-name">PATH</span>=<span class="org-string">"/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"</span>
<span class="org-builtin">export</span> PATH
<span class="org-keyword">exit</span> $<span class="org-variable-name">exit</span>
;;
<span class="org-keyword">esac</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf">
+<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><code>
<span class="org-type">define command</span> {
command_name inst_sensors
command_line /usr/local/sbin/inst_sensors
service_description Temperature Sensors
check_command inst_sensors
}
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orge20967c" class="outline-4">
-<h4 id="orge20967c"><span class="section-number-4">8.21.3.</span> Configure NAGIOS Monitors for Remote Hosts</h4>
+<div id="outline-container-org4c8f989" class="outline-4">
+<h4 id="org4c8f989"><span class="section-number-4">8.21.3.</span> Configure NAGIOS Monitors for Remote Hosts</h4>
<div class="outline-text-4" id="text-8-21-3">
<p>
The following sections contain code blocks specifying monitors for
commands are defined in code blocks interleaved with the blocks that
monitor them. The command blocks are appended to <q>nrpe.cfg</q> and the
monitoring blocks to <q>nagios.cfg</q>. The <q>nrpe.cfg</q> file is installed
-on each campus host by the campus role's <a href="#orgbd0ce38">Configure NRPE</a> tasks.
+on each campus host by the campus role's <a href="#org356ce5d">Configure NRPE</a> tasks.
</p>
</div>
</div>
-<div id="outline-container-orgfe68c96" class="outline-4">
-<h4 id="orgfe68c96"><span class="section-number-4">8.21.4.</span> Configure NAGIOS Monitors for Gate</h4>
+<div id="outline-container-org5f33bb4" class="outline-4">
+<h4 id="org5f33bb4"><span class="section-number-4">8.21.4.</span> Configure NAGIOS Monitors for Gate</h4>
<div class="outline-text-4" id="text-8-21-4">
<p>
Define the monitored host, <code>gate</code>. Monitor its response to network
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf">
+<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><code>
<span class="org-type">define host</span> {
use linux-server
host_name gate
address {{ gate_addr }}
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/campus/files/nrpe.cfg"><q>roles_t/campus/files/nrpe.cfg</q></a><pre class="src src-conf"><span class="org-variable-name">command</span>[<span class="org-constant">inst_root</span>]=/usr/lib/nagios/plugins/check_disk -w 20% -c 10% -p /
-</pre>
+<a href="roles_t/campus/files/nrpe.cfg"><q>roles_t/campus/files/nrpe.cfg</q></a><pre class="src src-conf"><code><span class="org-variable-name">command</span>[<span class="org-constant">inst_root</span>]=/usr/lib/nagios/plugins/check_disk -w 20% -c 10% -p /
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf">
+<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><code>
<span class="org-type">define service</span> {
use generic-service
host_name gate
service_description Root Partition
check_command check_nrpe!inst_root
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf">
+<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><code>
<span class="org-type">define service</span> {
use generic-service
host_name gate
service_description Current Load
check_command check_nrpe!check_load
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf">
+<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><code>
<span class="org-type">define service</span> {
use generic-service
host_name gate
service_description Total Processes
check_command check_nrpe!check_total_procs
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/campus/files/nrpe.cfg"><q>roles_t/campus/files/nrpe.cfg</q></a><pre class="src src-conf"><span class="org-variable-name">command</span>[<span class="org-constant">inst_swap</span>]=/usr/lib/nagios/plugins/check_swap -w 20% -c 10%
-</pre>
+<a href="roles_t/campus/files/nrpe.cfg"><q>roles_t/campus/files/nrpe.cfg</q></a><pre class="src src-conf"><code><span class="org-variable-name">command</span>[<span class="org-constant">inst_swap</span>]=/usr/lib/nagios/plugins/check_swap -w 20% -c 10%
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf">
+<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><code>
<span class="org-type">define service</span> {
use generic-service
host_name gate
service_description Swap Usage
check_command check_nrpe!inst_swap
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/campus/files/nrpe.cfg"><q>roles_t/campus/files/nrpe.cfg</q></a><pre class="src src-conf"><span class="org-variable-name">command</span>[<span class="org-constant">inst_sensors</span>]=/usr/local/sbin/inst_sensors
-</pre>
+<a href="roles_t/campus/files/nrpe.cfg"><q>roles_t/campus/files/nrpe.cfg</q></a><pre class="src src-conf"><code><span class="org-variable-name">command</span>[<span class="org-constant">inst_sensors</span>]=/usr/local/sbin/inst_sensors
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf">
+<a href="roles_t/core/templates/nagios.cfg"><q>roles_t/core/templates/nagios.cfg</q></a><pre class="src src-conf"><code>
<span class="org-type">define service</span> {
use generic-service
host_name gate
service_description Temperature Sensors
check_command check_nrpe!inst_sensors
}
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-org04cc272" class="outline-3">
-<h3 id="org04cc272"><span class="section-number-3">8.22.</span> Configure Backups</h3>
+<div id="outline-container-org2323be4" class="outline-3">
+<h3 id="org2323be4"><span class="section-number-3">8.22.</span> Configure Backups</h3>
<div class="outline-text-3" id="text-8-22">
<p>
The following task installs the <q>backup</q> script from <a href="private/"><q>private/</q></a>. An
-example script is provided in <a href="#org9d5954c">here</a>.
+example script is provided in <a href="#org8d148e8">here</a>.
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install backup script.
become: yes
copy:
src: ../private/backup
dest: /usr/local/sbin/backup
<span class="org-variable-name">mode: u</span>=rx,g=r,o=
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgd97190a" class="outline-3">
-<h3 id="orgd97190a"><span class="section-number-3">8.23.</span> Configure Nextcloud</h3>
+<div id="outline-container-org640e4f7" class="outline-3">
+<h3 id="org640e4f7"><span class="section-number-3">8.23.</span> Configure Nextcloud</h3>
<div class="outline-text-3" id="text-8-23">
<p>
Core runs Nextcloud to provide a private institute cloud, as described
-in <a href="#org71fc0ac">The Cloud Service</a>. Installing, restoring (from backup), and
+in <a href="#orgd0834d2">The Cloud Service</a>. Installing, restoring (from backup), and
upgrading Nextcloud are manual processes documented in <a href="https://docs.nextcloud.com/server/latest/admin_manual/maintenance/">The Nextcloud
Admin Manual, Maintenance</a>. However Ansible can help prepare Core
before an install or restore, and perform basic security checks
afterwards.
</p>
</div>
-<div id="outline-container-orga7bf888" class="outline-4">
-<h4 id="orga7bf888"><span class="section-number-4">8.23.1.</span> Prepare Core For Nextcloud</h4>
+<div id="outline-container-orgea15814" class="outline-4">
+<h4 id="orgea15814"><span class="section-number-4">8.23.1.</span> Prepare Core For Nextcloud</h4>
<div class="outline-text-4" id="text-8-23-1">
<p>
The Ansible code contained herein prepares Core to run Nextcloud by
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install packages required by Nextcloud.
become: yes
apt:
php-curl, php-gd, php-gmp, php-json, php-mysql,
php-mbstring, php-intl, php-imagick, php-xml, php-zip,
libapache2-mod-php ]
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Enable Apache2 modules for Nextcloud.
become: yes
apache2_module:
name: <span class="org-string">"{{ item }}"</span>
loop: [ rewrite, headers, env, dir, mime ]
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/files/nextcloud.conf"><q>roles_t/core/files/nextcloud.conf</q></a><pre class="src src-conf">Alias /nextcloud <span class="org-string">"/var/www/nextcloud/"</span>
+<a href="roles_t/core/files/nextcloud.conf"><q>roles_t/core/files/nextcloud.conf</q></a><pre class="src src-conf"><code>Alias /nextcloud <span class="org-string">"/var/www/nextcloud/"</span>
<Directory /var/www/nextcloud/>
Require all granted
Dav off
</IfModule>
</Directory>
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Nextcloud web configuration.
become: yes
copy:
cmd: a2ensite nextcloud
creates: /etc/apache2/sites-enabled/nextcloud.conf
notify: Restart Apache2.
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/files/nextcloud.conf"><q>roles_t/core/files/nextcloud.conf</q></a><pre class="src src-conf">
+<a href="roles_t/core/files/nextcloud.conf"><q>roles_t/core/files/nextcloud.conf</q></a><pre class="src src-conf"><code>
<Directory /var/www/html/>
<IfModule mod_rewrite.c>
RewriteEngine on
<span class="org-variable-name">/nextcloud/index.php/.well-known/nodeinfo [R</span>=301,L]
</IfModule>
</Directory>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/files/nextcloud.conf"><q>roles_t/core/files/nextcloud.conf</q></a><pre class="src src-conf">
+<a href="roles_t/core/files/nextcloud.conf"><q>roles_t/core/files/nextcloud.conf</q></a><pre class="src src-conf"><code>
<IfModule mod_headers.c>
Header always set \
Strict-Transport-Security <span class="org-string">"max-age=15552000; includeSubDomains"</span>
</IfModule>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Add {{ ansible_user }} to web server group.
become: yes
user:
name: <span class="org-string">"{{ ansible_user }}"</span>
append: yes
groups: www-data
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Create Nextcloud cron job.
become: yes
cron:
&& /usr/bin/php -f /var/www/nextcloud/cron.php
name: Nextcloud
user: www-data
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">nextcloud_dbpass: ippAgmaygyob
-</pre>
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>nextcloud_dbpass: ippAgmaygyob
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-conf">
+<pre class="src src-conf"><code>
- name: Create Nextcloud DB.
become: yes
mysql_db:
name: nextcloud
collation: utf8mb4_general_ci
encoding: utf8mb4
-</pre>
+</code></pre>
</div>
<p>
The following task would work (<code>mysql_user</code> supports
<code>check_implicit_admin</code>) <i>but</i> the <code>nextcloud</code> database was not created
above. Thus both database and user are created manually, with SQL
-given in the <a href="#orga610911">8.23.5</a> subsection below, before <code>occ
+given in the <a href="#orgb7a7660">8.23.5</a> subsection below, before <code>occ
maintenance:install</code> can run.
</p>
<div class="org-src-container">
-<pre class="src src-conf">
+<pre class="src src-conf"><code>
- name: Create Nextcloud DB user.
become: yes
mysql_user:
password: <span class="org-string">"{{ nextcloud_dbpass }}"</span>
update_password: always
priv: <span class="org-string">'nextcloud.*:all'</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Link /var/www/nextcloud.
become: yes
file:
state: link
force: yes
follow: no
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org06f8ed1" class="outline-4">
-<h4 id="org06f8ed1"><span class="section-number-4">8.23.2.</span> Configure PHP</h4>
+<div id="outline-container-org3f0d821" class="outline-4">
+<h4 id="org3f0d821"><span class="section-number-4">8.23.2.</span> Configure PHP</h4>
<div class="outline-text-4" id="text-8-23-2">
<p>
The following tasks set a number of PHP parameters for better
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Set PHP memory_limit for Nextcloud.
become: yes
lineinfile:
creates: /etc/php/8.2/apache2/conf.d/20-{{ item }}.ini
loop: [ nextcloud, apcu ]
notify: Restart Apache2.
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org45a4a2a" class="outline-4">
-<h4 id="org45a4a2a"><span class="section-number-4">8.23.3.</span> Create <q>/Nextcloud/</q></h4>
+<div id="outline-container-orgdb3439f" class="outline-4">
+<h4 id="orgdb3439f"><span class="section-number-4">8.23.3.</span> Create <q>/Nextcloud/</q></h4>
<div class="outline-text-4" id="text-8-23-3">
<p>
The Ansible tasks up to this point have completed Core's LAMP stack
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo mkdir /Nextcloud
+<pre class="src src-sh"><code>sudo mkdir /Nextcloud
sudo chmod 775 /Nextcloud
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo mkdir /home/nextcloud
+<pre class="src src-sh"><code>sudo mkdir /home/nextcloud
sudo chmod 775 /home/nextcloud
sudo ln -s /home/nextcloud /Nextcloud
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo mkfs -t ext4 /dev/sdb
+<pre class="src src-sh"><code>sudo mkfs -t ext4 /dev/sdb
sudo mkdir /Nextcloud
<span class="org-builtin">echo</span> <span class="org-string">"/dev/sdb /Nextcloud ext4 errors=remount-ro 0 2"</span> <span class="org-sh-escaped-newline">\</span>
| sudo tee -a /etc/fstab >/dev/null
sudo mount /Nextcloud
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org0568172" class="outline-4">
-<h4 id="org0568172"><span class="section-number-4">8.23.4.</span> Restore Nextcloud</h4>
+<div id="outline-container-org3c8ed7b" class="outline-4">
+<h4 id="org3c8ed7b"><span class="section-number-4">8.23.4.</span> Restore Nextcloud</h4>
<div class="outline-text-4" id="text-8-23-4">
<p>
Restoring Nextcloud in the newly created <q>/Nextcloud/</q> presumably
</p>
<div class="org-src-container">
-<pre class="src src-sh">rsync -a /media/sysadm/Backup/Nextcloud/ /Nextcloud/
-</pre>
+<pre class="src src-sh"><code>rsync -a /media/sysadm/Backup/Nextcloud/ /Nextcloud/
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo chown -R www-data.www-data /Nextcloud/nextcloud/
-</pre>
+<pre class="src src-sh"><code>sudo chown -R www-data.www-data /Nextcloud/nextcloud/
+</code></pre>
</div>
<p>
last dump was made February 20th 2022 and thus was saved in
<q>/Nextcloud/20220220.bak</q>. The database will need to be
created first as when installing Nextcloud. The appropriate SQL are
-given in <a href="#orga610911">Install Nextcloud</a> below.
+given in <a href="#orgb7a7660">Install Nextcloud</a> below.
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-builtin">cd</span> /Nextcloud/
+<pre class="src src-sh"><code><span class="org-builtin">cd</span> /Nextcloud/
sudo mysql --defaults-file=dbbackup.cnf nextcloud < 20220220.bak
<span class="org-builtin">cd</span> nextcloud/
sudo -u www-data php occ maintenance:data-fingerprint
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-orga610911" class="outline-4">
-<h4 id="orga610911"><span class="section-number-4">8.23.5.</span> Install Nextcloud</h4>
+<div id="outline-container-orgb7a7660" class="outline-4">
+<h4 id="orgb7a7660"><span class="section-number-4">8.23.5.</span> Install Nextcloud</h4>
<div class="outline-text-4" id="text-8-23-5">
<p>
Installing Nextcloud in the newly created <q>/Nextcloud/</q> starts with
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-builtin">cd</span> /Nextcloud/
+<pre class="src src-sh"><code><span class="org-builtin">cd</span> /Nextcloud/
tar xzf ~/Downloads/nextcloud-23.0.0.tar.bz2
sudo chown -R www-data.www-data nextcloud
sudo find nextcloud -type d -exec chmod 750 {} <span class="org-string">\;</span>
sudo find nextcloud -type f -exec chmod 640 {} <span class="org-string">\;</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sql"><span class="org-keyword">create</span> database nextcloud
+<pre class="src src-sql"><code><span class="org-keyword">create</span> database nextcloud
<span class="org-type">character</span> <span class="org-keyword">set</span> utf8mb4
<span class="org-keyword">collate</span> utf8mb4_general_ci;
<span class="org-keyword">grant</span> <span class="org-keyword">all</span> <span class="org-keyword">on</span> nextcloud.*
<span class="org-keyword">to</span> <span class="org-string">'nextclouduser'</span>@<span class="org-string">'localhost'</span>
identified <span class="org-keyword">by</span> <span class="org-string">'ippAgmaygyobwyt5'</span>;
flush <span class="org-keyword">privileges</span>;
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-builtin">cd</span> /var/www/nextcloud/
+<pre class="src src-sh"><code><span class="org-builtin">cd</span> /var/www/nextcloud/
sudo -u www-data php occ maintenance:install <span class="org-sh-escaped-newline">\</span>
--data-dir=/var/www/nextcloud/data <span class="org-sh-escaped-newline">\</span>
--database=mysql --database-name=nextcloud <span class="org-sh-escaped-newline">\</span>
--database-user=nextclouduser <span class="org-sh-escaped-newline">\</span>
--database-pass=ippAgmaygyobwyt5 <span class="org-sh-escaped-newline">\</span>
--admin-user=sysadm --admin-pass=PASSWORD
-</pre>
+</code></pre>
</div>
<p>
<p>
Before calling Nextcloud "configured", the administrator runs <code>./inst
-config core</code>, surfs to <code>http://core.small.private/nextcloud/</code>,
-logins in as <code>sysadm</code>, and follows any reasonable
-instructions (reasonable for a small organization) on the
+config core</code>, surfs to <code>https://core.small.private/nextcloud/</code>, logins
+in as <code>sysadm</code>, and follows any reasonable instructions on the
Administration > Overview page.
</p>
</div>
</div>
-<div id="outline-container-org380598a" class="outline-4">
-<h4 id="org380598a"><span class="section-number-4">8.23.6.</span> Afterwards</h4>
+<div id="outline-container-orgdc9a64a" class="outline-4">
+<h4 id="orgdc9a64a"><span class="section-number-4">8.23.6.</span> Afterwards</h4>
<div class="outline-text-4" id="text-8-23-6">
<p>
Whether Nextcloud was restored or installed, there are a few things
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Test for /Nextcloud/nextcloud/.
stat:
path: /Nextcloud/nextcloud
- debug:
msg: <span class="org-string">"/Nextcloud/ does not yet exist"</span>
when: not nextcloud.stat.exists
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure Nextcloud trusted domains.
become: yes
replace:
insertbefore: <span class="org-string">"^[)];"</span>
firstmatch: yes
when: nextcloud.stat.exists
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure Nextcloud memcache.
become: yes
lineinfile:
insertbefore: <span class="org-string">"^[)];"</span>
firstmatch: yes
when: nextcloud.stat.exists
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure Nextcloud for Pretty URLs.
become: yes
lineinfile:
- regexp: <span class="org-string">"^ *'htaccess.RewriteBase' *=>"</span>
line: <span class="org-string">" 'htaccess.RewriteBase' => '/nextcloud',"</span>
when: nextcloud.stat.exists
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">nextcloud_region: US
-</pre>
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>nextcloud_region: US
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure Nextcloud phone region.
become: yes
lineinfile:
insertbefore: <span class="org-string">"^[)];"</span>
firstmatch: yes
when: nextcloud.stat.exists
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Create /Nextcloud/dbbackup.cnf.
no_log: yes
become: yes
<span class="org-variable-name">regexp: password</span>=
<span class="org-variable-name">line: password</span>={{ nextcloud_dbpass }}
when: nextcloud.stat.exists
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
</div>
-<div id="outline-container-org72d6fde" class="outline-2">
-<h2 id="org72d6fde"><span class="section-number-2">9.</span> The Gate Role</h2>
+<div id="outline-container-org936487d" class="outline-2">
+<h2 id="org936487d"><span class="section-number-2">9.</span> The Gate Role</h2>
<div class="outline-text-2" id="text-9">
<p>
-The <code>gate</code> role configures the services expected at the campus gate: a
-VPN into the campus network via a campus Wi-Fi access point, and
-Internet access via NAT to the Internet. The gate machine uses
-three network interfaces (see <a href="#org24e627c">The Gate Machine</a>) configured with
-persistent names used in its firewall rules.
+The <code>gate</code> role configures the services expected at the campus gate:
+access to the private Ethernet from the untrusted Ethernet (e.g. a
+campus Wi-Fi AP) via VPN, and access to the Internet via NAT. The
+gate machine uses three network interfaces (see <a href="#org40481f7">The Gate Machine</a>)
+configured with persistent names used in its firewall rules.
</p>
<dl class="org-dl">
<dt><code>lan</code></dt><dd>The campus Ethernet.</dd>
-<dt><code>wifi</code></dt><dd>The campus Wi-Fi AP.</dd>
+<dt><code>wild</code></dt><dd>The campus IoT (Wi-Fi APs).</dd>
<dt><code>isp</code></dt><dd>The campus ISP.</dd>
</dl>
<p>
-Requiring a VPN to access the campus network from the campus Wi-Fi
-bolsters the native Wi-Fi encryption and frustrates non-RYF (<a href="https://ryf.fsf.org">Respects
-Your Freedom</a>) wireless equipment.
+Requiring a VPN to access the campus network from the untrusted
+Ethernet (a campus Wi-Fi AP) bolsters the native Wi-Fi encryption and
+frustrates non-RYF (<a href="https://ryf.fsf.org">Respects Your Freedom</a>) wireless equipment.
</p>
<p>
configurations, etc.
</p>
</div>
-<div id="outline-container-org0a4dc99" class="outline-3">
-<h3 id="org0a4dc99"><span class="section-number-3">9.1.</span> Include Particulars</h3>
+<div id="outline-container-orge1f832f" class="outline-3">
+<h3 id="orge1f832f"><span class="section-number-3">9.1.</span> Include Particulars</h3>
<div class="outline-text-3" id="text-9-1">
<p>
The following should be familiar boilerplate by now.
</p>
<div class="org-src-container">
-<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf">---
+<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf"><code>---
- name: Include public variables.
include_vars: ../public/vars.yml
tags: accounts
- name: Include members.
include_vars: <span class="org-string">"{{ lookup('first_found', membership_rolls) }}"</span>
tags: accounts
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org1e2857f" class="outline-3">
-<h3 id="org1e2857f"><span class="section-number-3">9.2.</span> Configure Netplan <a id="org176e1b0"></a></h3>
+<div id="outline-container-org73026e0" class="outline-3">
+<h3 id="org73026e0"><span class="section-number-3">9.2.</span> Configure Netplan <a id="orgfd4af3f"></a></h3>
<div class="outline-text-3" id="text-9-2">
<p>
Gate's network interfaces are configured using Netplan and two files.
<q>/etc/netplan/60-gate.yaml</q> describes the static interfaces, to the
-campus Ethernet and WiFi. <q>/etc/netplan/60-isp.yaml</q> is expected to
+campus Ethernet and Wi-Fi. <q>/etc/netplan/60-isp.yaml</q> is expected to
be revised more frequently as the campus ISP changes.
</p>
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">gate_lan_mac: 08:00:27:f3:16:79
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>gate_lan_mac: 08:00:27:f3:16:79
+gate_wild_mac: 08:00:27:4a:de:d2
gate_isp_mac: 08:00:27:3d:42:e5
-gate_wifi_mac: 08:00:27:4a:de:d2
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install netplan (gate).
become: yes
<span class="org-variable-name">apt: pkg</span>=netplan.io
routes:
- to: {{ public_vpn_net_cidr }}
via: {{ core_addr }}
- wifi:
+ wild:
match:
- macaddress: {{ gate_wifi_mac }}
- addresses: [ {{ gate_wifi_addr_cidr }} ]
- set-name: wifi
+ macaddress: {{ gate_wild_mac }}
+ addresses: [ {{ gate_wild_addr_cidr }} ]
+ set-name: wild
dhcp4: false
dest: /etc/netplan/60-gate.yaml
<span class="org-variable-name">mode: u</span>=rw,g=r,o=
<span class="org-variable-name">mode: u</span>=rw,g=r,o=
force: no
notify: Apply netplan.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/gate/handlers/main.yml"><q>roles_t/gate/handlers/main.yml</q></a><pre class="src src-conf">---
+<a href="roles_t/gate/handlers/main.yml"><q>roles_t/gate/handlers/main.yml</q></a><pre class="src src-conf"><code>---
- name: Apply netplan.
become: yes
command: netplan apply
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-orga752cf7" class="outline-3">
-<h3 id="orga752cf7"><span class="section-number-3">9.3.</span> UFW Rules</h3>
+<div id="outline-container-orge89b196" class="outline-3">
+<h3 id="orge89b196"><span class="section-number-3">9.3.</span> UFW Rules</h3>
<div class="outline-text-3" id="text-9-3">
<p>
Gate uses the Uncomplicated FireWall (UFW) to install its packet
NAT is enabled per the <code>ufw-framework(8)</code> manual page, by introducing
<code>nat</code> table rules in a block at the end of <q>/etc/ufw/before.rules</q>.
They translate packets going to the ISP. These can come from the
-private Ethernet or campus Wi-Fi. Hosts on the other institute
-networks (the two VPNs) should not be routing their Internet traffic
-through their VPN.
+private Ethernet or the untrusted Ethernet (campus IoT, including
+Wi-Fi APs). Hosts on the other institute networks (the two VPNs)
+should not be routing their Internet traffic through their VPN.
</p>
<div class="org-src-container">
-<code>ufw-nat</code><pre class="src src-conf" id="org059a7f2">-A POSTROUTING -s {{ private_net_cidr }} -o isp -j MASQUERADE
--A POSTROUTING -s {{ gate_wifi_net_cidr }} -o isp -j MASQUERADE
-</pre>
+<code>ufw-nat</code><pre class="src src-conf" id="org2b6b37d"><code>-A POSTROUTING -s {{ private_net_cidr }} -o isp -j MASQUERADE
+-A POSTROUTING -s {{ wild_net_cidr }} -o isp -j MASQUERADE
+</code></pre>
</div>
<p>
Forwarding rules are also needed. The <code>nat</code> table is a <i>post</i> routing
rule set, so the default routing policy (<code>DENY</code>) will drop packets
before NAT can translate them. The following rules are added to allow
-packets to be forwarded from the campus Ethernet or Gate-WiFi subnet
+packets to be forwarded from the campus Ethernet or its wild subnet
to an ISP on the <code>isp</code> interface, and back (if related to an outgoing
packet).
</p>
<div class="org-src-container">
-<code>ufw-forward-nat</code><pre class="src src-conf" id="org6c6443f">-A FORWARD -i lan -o isp -j ACCEPT
--A FORWARD -i wifi -o isp -j ACCEPT
+<code>ufw-forward-nat</code><pre class="src src-conf" id="org63ab446"><code>-A FORWARD -i lan -o isp -j ACCEPT
+-A FORWARD -i wild -o isp -j ACCEPT
-A FORWARD -i isp -o lan {{ ACCEPT_RELATED }}
--A FORWARD -i isp -o wifi {{ ACCEPT_RELATED }}
-</pre>
+-A FORWARD -i isp -o wild {{ ACCEPT_RELATED }}
+</code></pre>
</div>
<p>
-m state --state ESTABLISHED,RELATED -j ACCEPT
</pre>
-
<p>
If "the standard <code>iptables-restore</code> syntax" as it is described in the
<code>ufw-framework</code> manual page, allows continuation lines, please let us
</p>
<div class="org-src-container">
-<code>ufw-forward-private</code><pre class="src src-conf" id="orgbf5f811">-A FORWARD -i lan -o ovpn -j ACCEPT
+<code>ufw-forward-private</code><pre class="src src-conf" id="org9b9c5a4"><code>-A FORWARD -i lan -o ovpn -j ACCEPT
-A FORWARD -i ovpn -o lan -j ACCEPT
-</pre>
+</code></pre>
</div>
<p>
Note that there are no forwarding rules to allow packets to pass from
-the <code>wifi</code> device to the <code>lan</code> device, just the <code>ovpn</code> device.
+the <code>wild</code> device to the <code>lan</code> device, just the <code>ovpn</code> device.
</p>
</div>
</div>
-<div id="outline-container-org092a0fa" class="outline-3">
-<h3 id="org092a0fa"><span class="section-number-3">9.4.</span> Install UFW</h3>
+<div id="outline-container-org036ac74" class="outline-3">
+<h3 id="org036ac74"><span class="section-number-3">9.4.</span> Install UFW</h3>
<div class="outline-text-3" id="text-9-4">
<p>
The following tasks install the Uncomplicated Firewall (UFW), set its
future ssh sessions. For this reason, Ansible <i>does not</i> enable the
firewall. The administrator must login and execute the following
command after Gate is configured or new gate is "in position"
-(connected to old Gate's <code>wifi</code> and <code>isp</code> networks).
+(connected to old Gate's <code>wild</code> and <code>isp</code> networks).
</p>
<pre class="example">
sudo ufw enable
</pre>
-
<div class="org-src-container">
-<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install UFW.
become:
<span class="org-variable-name">apt: pkg</span>=ufw
<<ufw-forward-private>>
COMMIT
insertafter: EOF
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org6b47f34" class="outline-3">
-<h3 id="org6b47f34"><span class="section-number-3">9.5.</span> Configure DHCP For The Gate-WiFi Ethernet</h3>
+<div id="outline-container-org43b50b8" class="outline-3">
+<h3 id="org43b50b8"><span class="section-number-3">9.5.</span> Configure DHCP For The Wild Ethernet</h3>
<div class="outline-text-3" id="text-9-5">
<p>
-To accommodate commodity Wi-Fi access points without re-configuring
-them, the institute attempts to look like an up-link, an ISP, e.g. a
-cable modem. Thus it expects the wireless AP to route non-local
-traffic out its WAN Ethernet port, and to get an IP address for the
-WAN port using DHCP. Thus Gate runs ISC's DHCP daemon configured to
-listen on one network interface, recognize exactly one client host,
-and provide that one client with an IP address and customary network
-parameters (default route, time server, etc.).
+To accommodate commodity Wi-Fi access points, as well as wired IoT
+appliances, without re-configuring them, the institute attempts to
+look like an up-link, an ISP, e.g. a cable modem (aka "router"). It
+expects a wireless AP (or IoT appliance) to route non-local traffic
+out its WAN (or only) Ethernet port, and to get an IP address for that
+port using DHCP. Thus Gate runs ISC's DHCP daemon configured to
+listen on one network interface, recognize a specific list of clients,
+and provide each with an IP address and customary network parameters
+(default route, time server, etc.), much as was done on Core for the
+private Ethernet.
</p>
<p>
-Two Ansible variables are needed to configure Gate's DHCP service,
-specifically the sole subnet host: <code>wifi_wan_name</code> is any word
-appropriate for identifying the Wi-Fi AP, and <code>wifi_wan_mac</code> is the
-AP's MAC address.
+The example configuration file, <a href="private/gate-dhcpd.conf"><q>private/gate-dhcpd.conf</q></a>, unlike
+<a href="private/core-dhcpd.conf"><q>private/core-dhcpd.conf</q></a>, does not need RFC3442 (Classless static
+routes). The wild, wired or wireless IoT need know nothing about the
+private network(s). This is just an example file, with a MAC address
+chosen to (probably?) match a VirtualBox test machine. In actual use
+<q>private/core-dhcpd.conf</q> refers to a replacement file.
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">wifi_wan_mac: 94:83:c4:19:7d:57
-wifi_wan_name: campus-wifi-ap
-</pre>
-</div>
+<a href="private/gate-dhcpd.conf"><q>private/gate-dhcpd.conf</q></a><pre class="src src-conf"><code>default-lease-time 3600;
+max-lease-time 7200;
-<p>
-If Gate is configured with <code>./abbey config gate</code> and then connected to
-actual networks (i.e. <i>not</i> rebooted), the following command is
-executed. If a new gate was configured with <code>./abbey config new-gate</code>
-and not rebooted, the following command would also be executed.
-</p>
+ddns-update-style none;
-<pre class="example">
-sudo systemctl start isc-dhcp-server
-</pre>
+authoritative;
+log-facility daemon;
-<p>
-If physically moved or rebooted for some other reason, the above
-command would not be necessary.
-</p>
+<span class="org-type">subnet 192.168.57.0 netmask 255.255.255.0</span> {
+ option subnet-mask 255.255.255.0;
+ option broadcast-address 192.168.57.255;
+ option routers 192.168.57.1;
+}
+
+<span class="org-type">host campus-wifi-ap</span> {
+ hardware ethernet 94:83:c4:19:7d:57;
+ fixed-address 192.168.57.2;
+}
+</code></pre>
+</div>
<p>
Installation and configuration of the DHCP daemon follows. Note that
-the daemon listens <i>only</i> on the Gate-WiFi network interface. Also
-note the drop-in <code>Requires</code> dependency, without which the DHCP server
-intermittently fails, finding the <code>wifi</code> interface has no IPv4
-addresses (or perhaps finding no <code>wifi</code> interface at all?).
+the daemon listens <i>only</i> on the <code>wild</code> network interface. Also note
+the drop-in <code>Requires</code> dependency, without which the DHCP server
+intermittently fails, finding the <code>wild</code> interface has no IPv4
+addresses (or perhaps finding no <code>wild</code> interface at all?).
</p>
<div class="org-src-container">
-<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install DHCP server.
become: yes
<span class="org-variable-name">apt: pkg</span>=isc-dhcp-server
become: yes
lineinfile:
path: /etc/default/isc-dhcp-server
- <span class="org-variable-name">line: INTERFACESv4</span>=<span class="org-string">"wifi"</span>
+ <span class="org-variable-name">line: INTERFACESv4</span>=<span class="org-string">"wild"</span>
<span class="org-variable-name">regexp: ^INTERFACESv4</span>=
notify: Restart DHCP server.
+- name: Configure DHCP subnet.
+ become: yes
+ copy:
+ src: ../private/gate-dhcpd.conf
+ dest: /etc/dhcp/dhcpd.conf
+ notify: Restart DHCP server.
+
- name: Configure DHCP server dependence on interface.
become: yes
copy:
dest: /etc/systemd/system/isc-dhcp-server.service.d/depend.conf
notify: Reload Systemd.
-- name: Configure DHCP for WiFiAP service.
- become: yes
- copy:
- content: |
- default-lease-time 3600;
- max-lease-time 7200;
- ddns-update-style none;
- authoritative;
- log-facility daemon;
-
- <span class="org-type">subnet {{ gate_wifi_net }} netmask {{ gate_wifi_net_mask }}</span> {
- option subnet-mask {{ gate_wifi_net_mask }};
- option broadcast-address {{ gate_wifi_broadcast }};
- option routers {{ gate_wifi_addr }};
- }
-
- <span class="org-type">host {{ wifi_wan_name }}</span> {
- hardware ethernet {{ wifi_wan_mac }};
- fixed-address {{ wifi_wan_addr }};
- }
- dest: /etc/dhcp/dhcpd.conf
- notify: Restart DHCP server.
-
-- name: Enable DHCP server.
+- name: Enable/Start DHCP server.
become: yes
systemd:
service: isc-dhcp-server
enabled: yes
-</pre>
+ state: started
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/gate/handlers/main.yml"><q>roles_t/gate/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/gate/handlers/main.yml"><q>roles_t/gate/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart DHCP server.
become: yes
systemd:
become: yes
systemd:
daemon-reload: yes
-</pre>
+</code></pre>
</div>
+
+<p>
+If Gate is configured with <code>./abbey config gate</code> and then connected to
+actual networks (i.e. <i>not</i> rebooted), the following command is
+executed. If a new gate was configured with <code>./abbey config new-gate</code>
+and not rebooted, the following command would also be executed.
+</p>
+
+<pre class="example">
+sudo systemctl start isc-dhcp-server
+</pre>
+
+<p>
+If physically moved or rebooted for some other reason, the above
+command would not be necessary.
+</p>
</div>
</div>
-<div id="outline-container-orgf647926" class="outline-3">
-<h3 id="orgf647926"><span class="section-number-3">9.6.</span> Install Server Certificate</h3>
+<div id="outline-container-org435e716" class="outline-3">
+<h3 id="org435e716"><span class="section-number-3">9.6.</span> Install Server Certificate</h3>
<div class="outline-text-3" id="text-9-6">
<p>
The (OpenVPN) server on Gate uses an institute certificate (and key)
</p>
<div class="org-src-container">
-<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install server certificate/key.
become: yes
copy:
- { path: <span class="org-string">"private/gate.{{ domain_priv }}"</span>, typ: key,
mode: <span class="org-string">"u=r,g=,o="</span> }
notify: Restart OpenVPN.
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orga48817c" class="outline-3">
-<h3 id="orga48817c"><span class="section-number-3">9.7.</span> Configure OpenVPN</h3>
+<div id="outline-container-org877d1b2" class="outline-3">
+<h3 id="org877d1b2"><span class="section-number-3">9.7.</span> Configure OpenVPN</h3>
<div class="outline-text-3" id="text-9-7">
<p>
Gate uses OpenVPN to provide the institute's campus VPN service. Its
</p>
<div class="org-src-container">
-<code>openvpn-gate-routes</code><pre class="src src-conf" id="org23c801d">push <span class="org-string">"route {{ private_net_and_mask }}"</span>
+<code>openvpn-gate-routes</code><pre class="src src-conf" id="org20aef17"><code>push <span class="org-string">"route {{ private_net_and_mask }}"</span>
push <span class="org-string">"route {{ public_vpn_net_and_mask }}"</span>
-</pre>
+</code></pre>
</div>
<p>
The complete OpenVPN configuration for Gate includes a <code>server</code>
option, the pushed routes mentioned above, and the common options
-discussed in <a href="#orgc2baf19">The VPN Services</a>.
+discussed in <a href="#org1ea6412">The VPN Services</a>.
</p>
<div class="org-src-container">
-<code>openvpn-gate</code><pre class="src src-conf" id="org95cfc89">server {{ campus_vpn_net_and_mask }}
+<code>openvpn-gate</code><pre class="src src-conf" id="orgd61aa9a"><code>server {{ campus_vpn_net_and_mask }}
client-config-dir /etc/openvpn/ccd
<<openvpn-gate-routes>>
<<openvpn-dev-mode>>
cert /etc/server.crt
key /etc/server.key
dh dh2048.pem
-tls-auth ta.key 0
-</pre>
+tls-crypt shared.key
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/gate/tasks/main.yml"><q>roles_t/gate/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install OpenVPN.
become: yes
<span class="org-variable-name">apt: pkg</span>=openvpn
<span class="org-variable-name">mode: u</span>=r,g=,o=
loop:
- { src: gate-dh2048.pem, dest: dh2048.pem }
- - { src: gate-ta.key, dest: ta.key }
+ - { src: gate-shared.key, dest: shared.key }
notify: Restart OpenVPN.
- name: Configure OpenVPN.
dest: /etc/openvpn/server.conf
<span class="org-variable-name">mode: u</span>=r,g=r,o=
notify: Restart OpenVPN.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/gate/handlers/main.yml"><q>roles_t/gate/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/gate/handlers/main.yml"><q>roles_t/gate/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart OpenVPN.
become: yes
systemd:
service: openvpn@server
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-org2d914f2" class="outline-2">
-<h2 id="org2d914f2"><span class="section-number-2">10.</span> The Campus Role</h2>
+<div id="outline-container-orgb271096" class="outline-2">
+<h2 id="orgb271096"><span class="section-number-2">10.</span> The Campus Role</h2>
<div class="outline-text-2" id="text-10">
<p>
The <code>campus</code> role configures generic campus server machines: network
configured manually.
</p>
</div>
-<div id="outline-container-org84fdcbf" class="outline-3">
-<h3 id="org84fdcbf"><span class="section-number-3">10.1.</span> Include Particulars</h3>
+<div id="outline-container-orgeb3c56c" class="outline-3">
+<h3 id="orgeb3c56c"><span class="section-number-3">10.1.</span> Include Particulars</h3>
<div class="outline-text-3" id="text-10-1">
<p>
The following should be familiar boilerplate by now.
</p>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">---
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>---
- name: Include public variables.
include_vars: ../public/vars.yml
- name: Include private variables.
include_vars: ../private/vars.yml
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgce42bc5" class="outline-3">
-<h3 id="orgce42bc5"><span class="section-number-3">10.2.</span> Configure Hostname</h3>
+<div id="outline-container-org6c045dd" class="outline-3">
+<h3 id="org6c045dd"><span class="section-number-3">10.2.</span> Configure Hostname</h3>
<div class="outline-text-3" id="text-10-2">
<p>
Clients should be using the expected host name.
</p>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure hostname.
become: yes
copy:
become: yes
command: hostname -F /etc/hostname
<span class="org-variable-name">when: inventory_hostname !</span>= ansible_hostname
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org87b2fe8" class="outline-3">
-<h3 id="org87b2fe8"><span class="section-number-3">10.3.</span> Configure Systemd Resolved</h3>
+<div id="outline-container-orgb5ed705" class="outline-3">
+<h3 id="orgb5ed705"><span class="section-number-3">10.3.</span> Configure Systemd Resolved</h3>
<div class="outline-text-3" id="text-10-3">
<p>
Campus machines use the campus name server on Core (or <code>dns.google</code>),
</p>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure resolved.
become: yes
lineinfile:
notify:
- Reload Systemd.
- Restart Systemd resolved.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/campus/handlers/main.yml"><q>roles_t/campus/handlers/main.yml</q></a><pre class="src src-conf">---
+<a href="roles_t/campus/handlers/main.yml"><q>roles_t/campus/handlers/main.yml</q></a><pre class="src src-conf"><code>---
- name: Reload Systemd.
become: yes
systemd:
systemd:
service: systemd-resolved
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orge768e1b" class="outline-3">
-<h3 id="orge768e1b"><span class="section-number-3">10.4.</span> Configure Systemd Timesyncd</h3>
+<div id="outline-container-orgc9318c9" class="outline-3">
+<h3 id="orgc9318c9"><span class="section-number-3">10.4.</span> Configure Systemd Timesyncd</h3>
<div class="outline-text-3" id="text-10-4">
<p>
The institute uses a common time reference throughout the campus.
</p>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Configure timesyncd.
become: yes
lineinfile:
path: /etc/systemd/timesyncd.conf
<span class="org-variable-name">line: NTP</span>=ntp.{{ domain_priv }}
notify: Restart systemd-timesyncd.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/campus/handlers/main.yml"><q>roles_t/campus/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/handlers/main.yml"><q>roles_t/campus/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart systemd-timesyncd.
become: yes
systemd:
service: systemd-timesyncd
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgd519148" class="outline-3">
-<h3 id="orgd519148"><span class="section-number-3">10.5.</span> Add Administrator to System Groups</h3>
+<div id="outline-container-org17d2e8d" class="outline-3">
+<h3 id="org17d2e8d"><span class="section-number-3">10.5.</span> Add Administrator to System Groups</h3>
<div class="outline-text-3" id="text-10-5">
<p>
The administrator often needs to read (directories of) log files owned
</p>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Add {{ ansible_user }} to system groups.
become: yes
user:
name: <span class="org-string">"{{ ansible_user }}"</span>
append: yes
groups: root,adm
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org66ef6c6" class="outline-3">
-<h3 id="org66ef6c6"><span class="section-number-3">10.6.</span> Install Unattended Upgrades</h3>
+<div id="outline-container-org1c6f15d" class="outline-3">
+<h3 id="org1c6f15d"><span class="section-number-3">10.6.</span> Install Unattended Upgrades</h3>
<div class="outline-text-3" id="text-10-6">
<p>
The institute prefers to install security updates as soon as possible.
</p>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install basic software.
become: yes
<span class="org-variable-name">apt: pkg</span>=unattended-upgrades
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgb964f6c" class="outline-3">
-<h3 id="orgb964f6c"><span class="section-number-3">10.7.</span> Configure Postfix on Campus</h3>
+<div id="outline-container-org990a25f" class="outline-3">
+<h3 id="org990a25f"><span class="section-number-3">10.7.</span> Configure Postfix on Campus</h3>
<div class="outline-text-3" id="text-10-7">
<p>
The Postfix settings used by the campus include message size, queue
</ul>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install Postfix.
become: yes
<span class="org-variable-name">apt: pkg</span>=postfix
service: postfix
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/campus/handlers/main.yml"><q>roles_t/campus/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/handlers/main.yml"><q>roles_t/campus/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Restart Postfix.
become: yes
systemd:
service: postfix
state: restarted
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgcdd657f" class="outline-3">
-<h3 id="orgcdd657f"><span class="section-number-3">10.8.</span> Set Domain Name</h3>
+<div id="outline-container-org2b656fb" class="outline-3">
+<h3 id="org2b656fb"><span class="section-number-3">10.8.</span> Set Domain Name</h3>
<div class="outline-text-3" id="text-10-8">
<p>
The host's fully qualified (private) domain name (FQDN) is set by an
</p>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Set domain name.
become: yes
vars:
path: /etc/hosts
regexp: <span class="org-string">"^127.0.1.1[ ].*"</span>
line: <span class="org-string">"127.0.1.1 {{ name }}.{{ domain_priv }} {{ name }}"</span>
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgbd0ce38" class="outline-3">
-<h3 id="orgbd0ce38"><span class="section-number-3">10.9.</span> Configure NRPE</h3>
+<div id="outline-container-org356ce5d" class="outline-3">
+<h3 id="org356ce5d"><span class="section-number-3">10.9.</span> Configure NRPE</h3>
<div class="outline-text-3" id="text-10-9">
<p>
Each campus host runs an NRPE (a NAGIOS Remote Plugin Executor)
server so that the NAGIOS4 server on Core can collect statistics. The
-NAGIOS service is discussed in the <a href="#orgbd0ce38">Configure NRPE</a> section of <a href="#orge7ebc83">The Core
+NAGIOS service is discussed in the <a href="#org356ce5d">Configure NRPE</a> section of <a href="#orge6d718e">The Core
Role</a>.
</p>
<div class="org-src-container">
-<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/tasks/main.yml"><q>roles_t/campus/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install NRPE.
become: yes
apt:
service: nagios-nrpe-server
enabled: yes
state: started
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/campus/handlers/main.yml"><q>roles_t/campus/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/campus/handlers/main.yml"><q>roles_t/campus/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Reload NRPE server.
become: yes
systemd:
service: nagios-nrpe-server
state: reloaded
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-orgff33e02" class="outline-2">
-<h2 id="orgff33e02"><span class="section-number-2">11.</span> The Ansible Configuration</h2>
+<div id="outline-container-orgda31017" class="outline-2">
+<h2 id="orgda31017"><span class="section-number-2">11.</span> The Ansible Configuration</h2>
<div class="outline-text-2" id="text-11">
<p>
The small institute uses Ansible to maintain the configuration of its
role(s) to each host. Examples of these files are included here, and
are used to test the roles. The example configuration applies the
institutional roles to VirtualBox machines prepared according to
-chapter <a href="#org74b454f">Testing</a>.
+chapter <a href="#org7832c43">Testing</a>.
</p>
<p>
separate revision history.
</p>
</div>
-<div id="outline-container-orgfefb674" class="outline-3">
-<h3 id="orgfefb674"><span class="section-number-3">11.1.</span> <q>ansible.cfg</q></h3>
+<div id="outline-container-orgf6e5306" class="outline-3">
+<h3 id="orgf6e5306"><span class="section-number-3">11.1.</span> <q>ansible.cfg</q></h3>
<div class="outline-text-3" id="text-11-1">
<p>
The Ansible configuration file <a href="ansible.cfg"><q>ansible.cfg</q></a> contains just a handful
of settings, some included just to create a test jig as described in
-<a href="#org74b454f">Testing</a>.
+<a href="#org7832c43">Testing</a>.
</p>
<ul class="org-ul">
that Python 3 can be expected on all institute hosts.</li>
<li><code>vault_password_file</code> is set to suppress prompts for the vault
password. The institute keeps its vault password in <a href="Secret/"><q>Secret/</q></a> (as
-described in <a href="#org6519b0c">Keys</a>) and thus sets this parameter to
+described in <a href="#org1c1be46">Keys</a>) and thus sets this parameter to
<a href="Secret/vault-password"><q>Secret/vault-password</q></a>.</li>
<li><code>inventory</code> is set to avoid specifying it on the command line.</li>
<li><code>roles_path</code> is set to the recently tangled roles files in
</ul>
<div class="org-src-container">
-<a href="ansible.cfg"><q>ansible.cfg</q></a><pre class="src src-conf">[<span class="org-type">defaults</span>]
+<a href="ansible.cfg"><q>ansible.cfg</q></a><pre class="src src-conf"><code>[<span class="org-type">defaults</span>]
<span class="org-variable-name">interpreter_python</span>=/usr/bin/python3
<span class="org-variable-name">vault_password_file</span>=Secret/vault-password
<span class="org-variable-name">inventory</span>=hosts
<span class="org-variable-name">roles_path</span>=roles_t
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgb932c38" class="outline-3">
-<h3 id="orgb932c38"><span class="section-number-3">11.2.</span> <q>hosts</q></h3>
+<div id="outline-container-orge7d3e33" class="outline-3">
+<h3 id="orge7d3e33"><span class="section-number-3">11.2.</span> <q>hosts</q></h3>
<div class="outline-text-3" id="text-11-2">
<p>
The Ansible inventory file <a href="hosts"><q>hosts</q></a> describes all of the institute's
</p>
<div class="org-src-container">
-<a href="hosts"><q>hosts</q></a><pre class="src src-conf" id="orgafeb78d">all:
+<a href="hosts"><q>hosts</q></a><pre class="src src-conf" id="org0b95976"><code>all:
vars:
ansible_user: sysadm
ansible_ssh_extra_args: -i Secret/ssh_admin/id_rsa
campus:
hosts:
gate:
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="Secret/become.yml"><q>Secret/become.yml</q></a><pre class="src src-conf">become_front: !vault |
+<a href="Secret/become.yml"><q>Secret/become.yml</q></a><pre class="src src-conf"><code>become_front: !vault |
$ANSIBLE_VAULT;1.1;AES256
3563626131333733666466393166323135383838666338666131336335326
3656437663032653333623461633866653462636664623938356563306264
0636537633139366333373933396637633034383132373064393939363231
636264323132370a393135666335303361326330623438613630333638393
1303632663738306634
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-org074c362" class="outline-3">
-<h3 id="org074c362"><span class="section-number-3">11.3.</span> <q>playbooks/site.yml</q></h3>
+<div id="outline-container-org723c67b" class="outline-3">
+<h3 id="org723c67b"><span class="section-number-3">11.3.</span> <q>playbooks/site.yml</q></h3>
<div class="outline-text-3" id="text-11-3">
<p>
The example <a href="playbooks/site.yml"><q>playbooks/site.yml</q></a> playbook (below) applies the
</p>
<div class="org-src-container">
-<a href="playbooks/site.yml"><q>playbooks/site.yml</q></a><pre class="src src-conf">---
+<a href="playbooks/site.yml"><q>playbooks/site.yml</q></a><pre class="src src-conf"><code>---
- name: Configure All
hosts: all
roles: [ all ]
- name: Configure Campus
hosts: campus
roles: [ campus ]
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orge85b5b4" class="outline-3">
-<h3 id="orge85b5b4"><span class="section-number-3">11.4.</span> <q>Secret/vault-password</q></h3>
+<div id="outline-container-org696cc09" class="outline-3">
+<h3 id="org696cc09"><span class="section-number-3">11.4.</span> <q>Secret/vault-password</q></h3>
<div class="outline-text-3" id="text-11-4">
<p>
As already mentioned, the small institute keeps its Ansible vault
</p>
<div class="org-src-container">
-<a href="Secret/vault-password"><q>Secret/vault-password</q></a><pre class="src src-conf" id="org3cd4611">alitysortstagess
-</pre>
+<a href="Secret/vault-password"><q>Secret/vault-password</q></a><pre class="src src-conf" id="org442ebbb"><code>alitysortstagess
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org0517849" class="outline-3">
-<h3 id="org0517849"><span class="section-number-3">11.5.</span> Creating A Working Ansible Configuration</h3>
+<div id="outline-container-org93d3d06" class="outline-3">
+<h3 id="org93d3d06"><span class="section-number-3">11.5.</span> Creating A Working Ansible Configuration</h3>
<div class="outline-text-3" id="text-11-5">
<p>
A working Ansible configuration can be "tangled" from this document to
-produce the test configuration described in the <a href="#org74b454f">Testing</a> chapter. The
+produce the test configuration described in the <a href="#org7832c43">Testing</a> chapter. The
tangling is done by Emacs's <code>org-babel-tangle</code> function and has
already been performed with the resulting tangle included in the
distribution with this document.
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-builtin">cd</span>
+<pre class="src src-sh"><code><span class="org-builtin">cd</span>
mkdir network
<span class="org-builtin">cd</span> network
git init
git submodule add git://birchwood-abbey.net/~puck/Institute
git add Institute
-</pre>
+</code></pre>
</div>
<p>
<q>public/</q> and <q>private/</q>.</li>
<li><q>~/net/Secret</q> would be a symbolic link to the (auto-mounted?)
location of the administrator's encrypted USB drive, as described in
-section <a href="#org6519b0c">Keys</a>.</li>
+section <a href="#org1c1be46">Keys</a>.</li>
</ul>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">cp -r Institute/roles_t Institute/roles
+<pre class="src src-sh"><code>cp -r Institute/roles_t Institute/roles
( <span class="org-builtin">cd</span> playbooks; ln -s ../Institute/playbooks/* . )
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">./Institute/inst config -n
-</pre>
+<pre class="src src-sh"><code>./Institute/inst config -n
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgb70ec0e" class="outline-3">
-<h3 id="orgb70ec0e"><span class="section-number-3">11.6.</span> Maintaining A Working Ansible Configuration</h3>
+<div id="outline-container-orgb3fb614" class="outline-3">
+<h3 id="orgb3fb614"><span class="section-number-3">11.6.</span> Maintaining A Working Ansible Configuration</h3>
<div class="outline-text-3" id="text-11-6">
<p>
The Ansible roles currently tangle into the <a href="roles_t/"><q>roles_t/</q></a> directory to
</div>
</div>
</div>
-<div id="outline-container-org1c6f4a8" class="outline-2">
-<h2 id="org1c6f4a8"><span class="section-number-2">12.</span> The Institute Commands</h2>
+<div id="outline-container-org5db480b" class="outline-2">
+<h2 id="org5db480b"><span class="section-number-2">12.</span> The Institute Commands</h2>
<div class="outline-text-2" id="text-12">
<p>
The institute's administrator uses a convenience script to reliably
to get their defaults from <q>./ansible.cfg</q>.
</p>
</div>
-<div id="outline-container-orgf00b9ce" class="outline-3">
-<h3 id="orgf00b9ce"><span class="section-number-3">12.1.</span> Sub-command Blocks</h3>
+<div id="outline-container-orgad96cbc" class="outline-3">
+<h3 id="orgad96cbc"><span class="section-number-3">12.1.</span> Sub-command Blocks</h3>
<div class="outline-text-3" id="text-12-1">
<p>
The code blocks in this chapter tangle into the <a href="inst"><q>inst</q></a> script. Each
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl"><span class="org-comment-delimiter">#</span><span class="org-comment">!/usr/bin/perl -w</span>
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code><span class="org-comment-delimiter">#</span><span class="org-comment">!/usr/bin/perl -w</span>
<span class="org-comment-delimiter">#</span>
<span class="org-comment-delimiter"># </span><span class="org-comment">DO NOT EDIT. This file was tangled from an institute.org file.</span>
<span class="org-keyword">use</span> <span class="org-constant">strict</span>;
<span class="org-keyword">use</span> <span class="org-constant">IO::File</span>;
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org20782dc" class="outline-3">
-<h3 id="org20782dc"><span class="section-number-3">12.2.</span> Sanity Check</h3>
+<div id="outline-container-org3b3c0fd" class="outline-3">
+<h3 id="org3b3c0fd"><span class="section-number-3">12.2.</span> Sanity Check</h3>
<div class="outline-text-3" id="text-12-2">
<p>
The next code block does not implement a sub-command; it implements
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">sub</span> <span class="org-function-name">note_missing_file_p</span> ($);
<span class="org-keyword">sub</span> <span class="org-function-name">note_missing_directory_p</span> ($);
<span class="org-keyword">return</span> 0;
}
}
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org10ec3d5" class="outline-3">
-<h3 id="org10ec3d5"><span class="section-number-3">12.3.</span> Importing Ansible Variables</h3>
+<div id="outline-container-org1a212b5" class="outline-3">
+<h3 id="org1a212b5"><span class="section-number-3">12.3.</span> Importing Ansible Variables</h3>
<div class="outline-text-3" id="text-12-3">
<p>
To ensure that Ansible and <code>./inst</code> are sympatico vis-a-vi certain
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-conf">
+<a href="inst"><q>inst</q></a><pre class="src src-conf"><code>
<span class="org-type">sub mysystem (@)</span> {
<span class="org-variable-name">my $line</span> = join (<span class="org-string">" "</span>, @_);
print <span class="org-string">"$line\n"</span>;
mysystem <span class="org-string">"ansible-playbook playbooks/check-inst-vars.yml >/dev/null"</span>;
-our ($domain_name, $domain_priv, $front_addr, $gate_wifi_addr);
+our ($domain_name, $domain_priv, $front_addr, $gate_wild_addr);
do <span class="org-string">"./private/vars.pl"</span>;
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="playbooks/check-inst-vars.yml"><q>playbooks/check-inst-vars.yml</q></a><pre class="src src-conf">- hosts: localhost
+<a href="playbooks/check-inst-vars.yml"><q>playbooks/check-inst-vars.yml</q></a><pre class="src src-conf"><code>- hosts: localhost
gather_facts: no
tasks:
- include_vars: ../public/vars.yml
<span class="org-variable-name">$domain_name</span> = <span class="org-string">"{{ domain_name }}"</span>;
<span class="org-variable-name">$domain_priv</span> = <span class="org-string">"{{ domain_priv }}"</span>;
<span class="org-variable-name">$front_addr</span> = <span class="org-string">"{{ front_addr }}"</span>;
- <span class="org-variable-name">$gate_wifi_addr</span> = <span class="org-string">"{{ gate_wifi_addr }}"</span>;
+ <span class="org-variable-name">$gate_wild_addr</span> = <span class="org-string">"{{ gate_wild_addr }}"</span>;
dest: ../private/vars.pl
<span class="org-variable-name">mode: u</span>=rw,g=,o=
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org671a111" class="outline-3">
-<h3 id="org671a111"><span class="section-number-3">12.4.</span> The CA Command</h3>
+<div id="outline-container-org3fe9e37" class="outline-3">
+<h3 id="org3fe9e37"><span class="section-number-3">12.4.</span> The CA Command</h3>
<div class="outline-text-3" id="text-12-4">
<p>
The next code block implements the <code>CA</code> sub-command, which creates a
</p>
<div class="org-src-container">
-<a href="public/vars.yml"><q>public/vars.yml</q></a><pre class="src src-conf">full_name: Small Institute LLC
-</pre>
+<a href="public/vars.yml"><q>public/vars.yml</q></a><pre class="src src-conf"><code>full_name: Small Institute LLC
+</code></pre>
</div>
<p>
ln -s /media/sysadm/ADE7-F866/ Secret
</pre>
-
<p>
The <a href="Secret/CA/"><q>Secret/CA/</q></a> directory is prepared using Easy RSA's <code>make-cadir</code>
command. The <a href="Secret/CA/vars"><q>Secret/CA/vars</q></a> file thus created is edited to contain
./inst CA
</pre>
-
<p>
Running <code>./inst CA</code> creates the new CA and keys. The command prompts
for the Common Name (or several levels of Organizational names) of the
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">if</span> (defined $<span class="org-variable-name">ARGV</span>[0] && $<span class="org-variable-name">ARGV</span>[0] eq <span class="org-string">"CA"</span>) {
<span class="org-keyword">die</span> <span class="org-string">"usage: $0 CA"</span> <span class="org-keyword">if</span> @<span class="org-perl-non-scalar-variable">ARGV</span> != 1;
<span class="org-keyword">die</span> <span class="org-string">"Secret/CA/easyrsa: not an executable\n"</span>
mysystem <span class="org-string">"cd Secret/CA; ./easyrsa build-server-full core.$pvt nopass"</span>;
mysystem <span class="org-string">"cd Secret/CA; ./easyrsa build-client-full core nopass"</span>;
umask 077;
- mysystem <span class="org-string">"openvpn --genkey secret Secret/front-ta.key"</span>;
- mysystem <span class="org-string">"openvpn --genkey secret Secret/gate-ta.key"</span>;
+ mysystem <span class="org-string">"openvpn --genkey secret Secret/front-shared.key"</span>;
+ mysystem <span class="org-string">"openvpn --genkey secret Secret/gate-shared.key"</span>;
mysystem <span class="org-string">"openssl dhparam -out Secret/front-dh2048.pem 2048"</span>;
mysystem <span class="org-string">"openssl dhparam -out Secret/gate-dh2048.pem 2048"</span>;
mysystem <span class="org-string">"ssh-keygen -A -f Secret/ssh_front -C $dom"</span>;
<span class="org-keyword">exit</span>;
}
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org5877bb0" class="outline-3">
-<h3 id="org5877bb0"><span class="section-number-3">12.5.</span> The Config Command</h3>
+<div id="outline-container-orge93c2cb" class="outline-3">
+<h3 id="orge93c2cb"><span class="section-number-3">12.5.</span> The Config Command</h3>
<div class="outline-text-3" id="text-12-5">
<p>
The next code block implements the <code>config</code> sub-command, which
provisions network services by running the <q>site.yml</q> playbook
-described in <a href="#org074c362"><q>playbooks/site.yml</q></a>. It recognizes an optional <code>-n</code>
+described in <a href="#org723c67b"><q>playbooks/site.yml</q></a>. It recognizes an optional <code>-n</code>
flag indicating that the service configurations should just be
checked. Given an optional host name, it provisions (or checks) just
the named host.
./inst config -n HOST
</pre>
-
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">if</span> (defined $<span class="org-variable-name">ARGV</span>[0] && $<span class="org-variable-name">ARGV</span>[0] eq <span class="org-string">"config"</span>) {
<span class="org-keyword">die</span> <span class="org-string">"Secret/CA/easyrsa: not executable\n"</span>
<span class="org-keyword">if</span> ! -x <span class="org-string">"Secret/CA/easyrsa"</span>;
mysystem $<span class="org-variable-name">cmd</span>;
<span class="org-keyword">exit</span>;
}
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orge7fe793" class="outline-3">
-<h3 id="orge7fe793"><span class="section-number-3">12.6.</span> Account Management</h3>
+<div id="outline-container-org6138e49" class="outline-3">
+<h3 id="org6138e49"><span class="section-number-3">12.6.</span> Account Management</h3>
<div class="outline-text-3" id="text-12-6">
<p>
For general information about members and their Unix accounts, see
-<a href="#org54da6ed">Accounts</a>. The account management sub-commands maintain a mapping
+<a href="#orga38c5ed">Accounts</a>. The account management sub-commands maintain a mapping
associating member "usernames" (Unix account names) with their
records. The mapping is stored among other things in
<q>private/members.yml</q> as the value associated with the key <code>members</code>.
</p>
<div class="org-src-container">
-<q>private/members.yml</q><pre class="src src-conf">---
+<q>private/members.yml</q><pre class="src src-conf"><code>---
members:
dick:
status: current
- dick
revoked:
- dick-phone
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="private/members-empty.yml"><q>private/members-empty.yml</q></a><pre class="src src-conf">---
+<a href="private/members-empty.yml"><q>private/members-empty.yml</q></a><pre class="src src-conf"><code>---
members:
usernames: []
revoked: []
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf">membership_rolls:
+<a href="private/vars.yml"><q>private/vars.yml</q></a><pre class="src src-conf"><code>membership_rolls:
- <span class="org-string">"../private/members.yml"</span>
- <span class="org-string">"../private/members-empty.yml"</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">use</span> <span class="org-constant">YAML::XS</span> qw<span class="org-string">(LoadFile DumpFile)</span>;
<span class="org-keyword">sub</span> <span class="org-function-name">read_members_yaml</span> () {
}
close $<span class="org-variable-name">O</span> or <span class="org-keyword">die</span> <span class="org-string">"Could not close $pathname: $!\n"</span>;
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">sub</span> <span class="org-function-name">print_member</span> ($$) {
<span class="org-keyword">my</span> ($<span class="org-variable-name">out</span>, $<span class="org-variable-name">member</span>) = @<span class="org-perl-non-scalar-variable">_</span>;
print $<span class="org-variable-name">out</span> <span class="org-string">" "</span>, $<span class="org-variable-name">member</span>->{<span class="org-string">"username"</span>}, <span class="org-string">":\n"</span>;
print $<span class="org-variable-name">out</span> <span class="org-string">" $key: "</span>, $<span class="org-variable-name">member</span>->{$<span class="org-variable-name">key</span>}, <span class="org-string">"\n"</span>;
}
}
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgebc3780" class="outline-3">
-<h3 id="orgebc3780"><span class="section-number-3">12.7.</span> The New Command</h3>
+<div id="outline-container-org541678b" class="outline-3">
+<h3 id="org541678b"><span class="section-number-3">12.7.</span> The New Command</h3>
<div class="outline-text-3" id="text-12-7">
<p>
The next code block implements the <code>new</code> sub-command. It adds a new
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">sub</span> <span class="org-function-name">valid_username</span> (@);
<span class="org-keyword">sub</span> <span class="org-function-name">shell_escape</span> ($);
<span class="org-keyword">sub</span> <span class="org-function-name">strip_vault</span> ($);
<span class="org-keyword">my</span> @<span class="org-perl-non-scalar-variable">lines</span> = split <span class="org-string">/^ */</span>m, $<span class="org-variable-name">string</span>;
<span class="org-keyword">return</span> (join <span class="org-string">""</span>, @<span class="org-perl-non-scalar-variable">lines</span>[1..$#<span class="org-perl-non-scalar-variable">lines</span>]);
}
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="playbooks/nextcloud-new.yml"><q>playbooks/nextcloud-new.yml</q></a><pre class="src src-conf">- hosts: core
+<a href="playbooks/nextcloud-new.yml"><q>playbooks/nextcloud-new.yml</q></a><pre class="src src-conf"><code>- hosts: core
no_log: yes
tasks:
- name: Run occ user:add.
args:
chdir: /var/www/nextcloud/
executable: /usr/bin/expect
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org0a5d277" class="outline-3">
-<h3 id="org0a5d277"><span class="section-number-3">12.8.</span> The Pass Command</h3>
+<div id="outline-container-org5e1c62d" class="outline-3">
+<h3 id="org5e1c62d"><span class="section-number-3">12.8.</span> The Pass Command</h3>
<div class="outline-text-3" id="text-12-8">
<p>
The institute's <code>passwd</code> command on Core securely emails <code>root</code> with a
message is sent to <code>member@core</code>.
</p>
</div>
-<div id="outline-container-org1e2a891" class="outline-4">
-<h4 id="org1e2a891"><span class="section-number-4">12.8.1.</span> Less Aggressive passwd.</h4>
+<div id="outline-container-orgdf2b1f0" class="outline-4">
+<h4 id="orgdf2b1f0"><span class="section-number-4">12.8.1.</span> Less Aggressive passwd.</h4>
<div class="outline-text-4" id="text-12-8-1">
<p>
The next code block implements the less aggressive <code>passwd</code> command.
</p>
<div class="org-src-container">
-<a href="roles_t/core/templates/passwd"><q>roles_t/core/templates/passwd</q></a><pre class="src src-perl"><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/perl -wT</span>
+<a href="roles_t/core/templates/passwd"><q>roles_t/core/templates/passwd</q></a><pre class="src src-perl"><code><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/perl -wT</span>
<span class="org-keyword">use</span> <span class="org-constant">strict</span>;
<span class="org-string">Your request was sent to Root. PLEASE WAIT for email confirmation</span>
<span class="org-string">that the change was completed.\n"</span>;
<span class="org-keyword">exit</span>;
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org9b6d5b8" class="outline-4">
-<h4 id="org9b6d5b8"><span class="section-number-4">12.8.2.</span> Less Aggressive Pass Command</h4>
+<div id="outline-container-org02d38d2" class="outline-4">
+<h4 id="org02d38d2"><span class="section-number-4">12.8.2.</span> Less Aggressive Pass Command</h4>
<div class="outline-text-4" id="text-12-8-2">
<p>
The following code block implements the <code>./inst pass</code> command, used by
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">use</span> <span class="org-constant">MIME::Base64</span>;
<span class="org-keyword">if</span> (defined $<span class="org-variable-name">ARGV</span>[0] && $<span class="org-variable-name">ARGV</span>[0] eq <span class="org-string">"pass"</span>) {
close $<span class="org-variable-name">O</span> or <span class="org-keyword">die</span> <span class="org-string">"pipe to sendmail failed: $!\n"</span>;
<span class="org-keyword">exit</span>;
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<a href="playbooks/nextcloud-pass.yml"><q>playbooks/nextcloud-pass.yml</q></a><pre class="src src-conf">- hosts: core
+<a href="playbooks/nextcloud-pass.yml"><q>playbooks/nextcloud-pass.yml</q></a><pre class="src src-conf"><code>- hosts: core
no_log: yes
tasks:
- name: Run occ user:resetpassword.
args:
chdir: /var/www/nextcloud/
executable: /usr/bin/expect
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org739e719" class="outline-4">
-<h4 id="org739e719"><span class="section-number-4">12.8.3.</span> Installing the Less Aggressive passwd</h4>
+<div id="outline-container-org77d62a8" class="outline-4">
+<h4 id="org77d62a8"><span class="section-number-4">12.8.3.</span> Installing the Less Aggressive passwd</h4>
<div class="outline-text-4" id="text-12-8-3">
<p>
The following Ansible tasks install the less aggressive <code>passwd</code>
</p>
<div class="org-src-container">
-<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/tasks/main.yml"><q>roles_t/core/tasks/main.yml</q></a><pre class="src src-conf"><code>
- name: Install institute passwd command.
become: yes
template:
dest: ~/.gnupg-root-pub.pem
<span class="org-variable-name">mode: u</span>=r,g=r,o=r
notify: Import root PGP key.
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf">
+<a href="roles_t/core/handlers/main.yml"><q>roles_t/core/handlers/main.yml</q></a><pre class="src src-conf"><code>
- name: Import root PGP key.
become: no
command: gpg --import ~/.gnupg-root-pub.pem
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-orga2f39ee" class="outline-3">
-<h3 id="orga2f39ee"><span class="section-number-3">12.9.</span> The Old Command</h3>
+<div id="outline-container-org2db4274" class="outline-3">
+<h3 id="org2db4274"><span class="section-number-3">12.9.</span> The Old Command</h3>
<div class="outline-text-3" id="text-12-9">
<p>
The <code>old</code> command disables a member's accounts and clients.
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">if</span> (defined $<span class="org-variable-name">ARGV</span>[0] && $<span class="org-variable-name">ARGV</span>[0] eq <span class="org-string">"old"</span>) {
<span class="org-keyword">my</span> $<span class="org-variable-name">user</span> = valid_username (@<span class="org-perl-non-scalar-variable">ARGV</span>);
<span class="org-keyword">my</span> $<span class="org-variable-name">yaml</span> = read_members_yaml ();
<span class="org-string">"-t accounts playbooks/site.yml"</span>);
<span class="org-keyword">exit</span>;
}
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="playbooks/nextcloud-old.yml"><q>playbooks/nextcloud-old.yml</q></a><pre class="src src-conf">- hosts: core
+<a href="playbooks/nextcloud-old.yml"><q>playbooks/nextcloud-old.yml</q></a><pre class="src src-conf"><code>- hosts: core
tasks:
- name: Run occ user:disable.
shell: |
args:
chdir: /var/www/nextcloud/
executable: /usr/bin/expect
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org0ad53cf" class="outline-3">
-<h3 id="org0ad53cf"><span class="section-number-3">12.10.</span> The Client Command</h3>
+<div id="outline-container-orgdc36b90" class="outline-3">
+<h3 id="orgdc36b90"><span class="section-number-3">12.10.</span> The Client Command</h3>
<div class="outline-text-3" id="text-12-10">
<p>
The <code>client</code> command creates an OpenVPN configuration (<q>.ovpn</q>) file
</p>
<div class="org-src-container">
-<code>openvpn-up</code><pre class="src src-conf" id="orgaef0340">script-security 2
+<code>openvpn-up</code><pre class="src src-conf" id="org87ee394"><code>script-security 2
up /etc/openvpn/update-systemd-resolved
up-restart
-</pre>
+</code></pre>
</div>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl"><span class="org-keyword">sub</span> <span class="org-function-name">write_template</span> ($$$$$$$$$);
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code><span class="org-keyword">sub</span> <span class="org-function-name">write_template</span> ($$$$$$$$$);
<span class="org-keyword">sub</span> <span class="org-function-name">read_file</span> ($);
<span class="org-keyword">sub</span> <span class="org-function-name">add_client</span> ($$$);
<span class="org-string"><<openvpn-up>>"</span>;
<span class="org-keyword">if</span> ($<span class="org-variable-name">type</span> ne <span class="org-string">"campus"</span>) {
- <span class="org-keyword">my</span> $<span class="org-variable-name">TA</span> = read_file <span class="org-string">"Secret/front-ta.key"</span>;
- write_template ($<span class="org-variable-name">DEV</span>,$<span class="org-variable-name">UP</span>,$<span class="org-variable-name">CA</span>,$<span class="org-variable-name">CRT</span>,$<span class="org-variable-name">KEY</span>,$<span class="org-variable-name">TA</span>, $<span class="org-variable-name">front_addr</span>,
+ <span class="org-keyword">my</span> $<span class="org-variable-name">TC</span> = read_file <span class="org-string">"Secret/front-shared.key"</span>;
+ write_template ($<span class="org-variable-name">DEV</span>,$<span class="org-variable-name">UP</span>,$<span class="org-variable-name">CA</span>,$<span class="org-variable-name">CRT</span>,$<span class="org-variable-name">KEY</span>,$<span class="org-variable-name">TC</span>, $<span class="org-variable-name">front_addr</span>,
$<span class="org-variable-name">domain_name</span>, <span class="org-string">"public.ovpn"</span>);
print <span class="org-string">"Wrote public VPN configuration to public.ovpn.\n"</span>;
}
- <span class="org-keyword">my</span> $<span class="org-variable-name">TA</span> = read_file <span class="org-string">"Secret/gate-ta.key"</span>;
- write_template ($<span class="org-variable-name">DEV</span>,$<span class="org-variable-name">UP</span>,$<span class="org-variable-name">CA</span>,$<span class="org-variable-name">CRT</span>,$<span class="org-variable-name">KEY</span>,$<span class="org-variable-name">TA</span>, $<span class="org-variable-name">gate_wifi_addr</span>,
+ <span class="org-keyword">my</span> $<span class="org-variable-name">TC</span> = read_file <span class="org-string">"Secret/gate-shared.key"</span>;
+ write_template ($<span class="org-variable-name">DEV</span>,$<span class="org-variable-name">UP</span>,$<span class="org-variable-name">CA</span>,$<span class="org-variable-name">CRT</span>,$<span class="org-variable-name">KEY</span>,$<span class="org-variable-name">TC</span>, $<span class="org-variable-name">gate_wild_addr</span>,
<span class="org-string">"gate.$domain_priv"</span>, <span class="org-string">"campus.ovpn"</span>);
print <span class="org-string">"Wrote campus VPN configuration to campus.ovpn.\n"</span>;
}
<span class="org-keyword">sub</span> <span class="org-function-name">write_template</span> ($$$$$$$$$) {
- <span class="org-keyword">my</span> ($<span class="org-variable-name">DEV</span>,$<span class="org-variable-name">UP</span>,$<span class="org-variable-name">CA</span>,$<span class="org-variable-name">CRT</span>,$<span class="org-variable-name">KEY</span>,$<span class="org-variable-name">TA</span>,$<span class="org-variable-name">ADDR</span>,$<span class="org-variable-name">NAME</span>,$<span class="org-variable-name">FILE</span>) = @<span class="org-perl-non-scalar-variable">_</span>;
+ <span class="org-keyword">my</span> ($<span class="org-variable-name">DEV</span>,$<span class="org-variable-name">UP</span>,$<span class="org-variable-name">CA</span>,$<span class="org-variable-name">CRT</span>,$<span class="org-variable-name">KEY</span>,$<span class="org-variable-name">TC</span>,$<span class="org-variable-name">ADDR</span>,$<span class="org-variable-name">NAME</span>,$<span class="org-variable-name">FILE</span>) = @<span class="org-perl-non-scalar-variable">_</span>;
<span class="org-keyword">my</span> $<span class="org-variable-name">O</span> = new IO::File;
open ($<span class="org-variable-name">O</span>, <span class="org-string">">$FILE.tmp"</span>) or <span class="org-keyword">die</span> <span class="org-string">"Could not open $FILE.tmp: $!\n"</span>;
print $<span class="org-variable-name">O</span> <span class="org-string">"client</span>
<span class="org-string"><ca>\n$CA</ca></span>
<span class="org-string"><cert>\n$CRT</cert></span>
<span class="org-string"><key>\n$KEY</key></span>
-<span class="org-string"><tls-auth>\n$TA</tls-auth>\n"</span>;
+<span class="org-string"><tls-crypt>\n$TC</tls-crypt>\n"</span>;
close $<span class="org-variable-name">O</span> or <span class="org-keyword">die</span> <span class="org-string">"Could not close $FILE.tmp: $!\n"</span>;
rename (<span class="org-string">"$FILE.tmp"</span>, $<span class="org-variable-name">FILE</span>)
or <span class="org-keyword">die</span> <span class="org-string">"Could not rename $FILE.tmp: $!\n"</span>;
close $<span class="org-variable-name">I</span> or <span class="org-keyword">die</span> <span class="org-string">"$path: could not close: $!\n"</span>;
<span class="org-keyword">return</span> $<span class="org-variable-name">c</span>;
}
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org875755b" class="outline-3">
-<h3 id="org875755b"><span class="section-number-3">12.11.</span> Institute Command Help</h3>
+<div id="outline-container-orgb98a15e" class="outline-3">
+<h3 id="orgb98a15e"><span class="section-number-3">12.11.</span> Institute Command Help</h3>
<div class="outline-text-3" id="text-12-11">
<p>
This should be the last block tangled into the <a href="inst"><q>inst</q></a> script. It
</p>
<div class="org-src-container">
-<a href="inst"><q>inst</q></a><pre class="src src-perl">
+<a href="inst"><q>inst</q></a><pre class="src src-perl"><code>
<span class="org-keyword">die</span> <span class="org-string">"usage: $0 [CA|config|new|pass|old|client] ...\n"</span>;
-</pre>
+</code></pre>
</div>
</div>
</div>
</div>
-<div id="outline-container-org74b454f" class="outline-2">
-<h2 id="org74b454f"><span class="section-number-2">13.</span> Testing</h2>
+<div id="outline-container-org7832c43" class="outline-2">
+<h2 id="org7832c43"><span class="section-number-2">13.</span> Testing</h2>
<div class="outline-text-2" id="text-13">
<p>
The example files in this document, <a href="ansible.cfg"><q>ansible.cfg</q></a> and <a href="hosts"><q>hosts</q></a> as well
as those in <a href="public/"><q>public/</q></a> and <a href="private/"><q>private/</q></a>, along with the matching EasyRSA
certificate authority and GnuPG key-ring in <a href="Secret/"><q>Secret/</q></a> (included in the
distribution), can be used to configure three VirtualBox VMs
-simulating Core, Gate and Front in test networks simulating a campus
-Ethernet, Wi-Fi, ISP, and a commercial cloud. With the test networks
-up and running, a simulated member's notebook can be created and
-alternately attached to the simulated campus Wi-Fi or the Internet (as
-though abroad). The administrator's notebook in this simulation is
-the VirtualBox host.
+simulating Core, Gate and Front in test networks simulating a private
+Ethernet, an untrusted Ethernet, the campus ISP, and a commercial
+cloud. With the test networks up and running, a simulated member's
+notebook can be created and alternately attached to the untrusted
+Ethernet (as though it were on the campus Wi-Fi) or the Internet (as
+though it were abroad). The administrator's notebook in this
+simulation is the VirtualBox host.
</p>
<p>
The next two sections list the steps taken to create the simulated
Core, Gate and Front machines, and connect them to their networks.
-The process is similar to that described in <a href="#org754e9f1">The (Actual) Hardware</a>, but
+The process is similar to that described in <a href="#orgbf29081">The (Actual) Hardware</a>, but
is covered in detail here where the VirtualBox hypervisor can be
assumed and exact command lines can be given (and copied during
re-testing). The remaining sections describe the manual testing
site at <a href="https://www.virtualbox.org/manual/UserManual.html">https://www.virtualbox.org/manual/UserManual.html</a>.
</p>
</div>
-<div id="outline-container-org6e2b33d" class="outline-3">
-<h3 id="org6e2b33d"><span class="section-number-3">13.1.</span> The Test Networks</h3>
+<div id="outline-container-orgf8057e6" class="outline-3">
+<h3 id="orgf8057e6"><span class="section-number-3">13.1.</span> The Test Networks</h3>
<div class="outline-text-3" id="text-13-1">
<p>
The networks used in the test:
machine at <code>192.168.56.10</code> pretending to be the administrator's
notebook.</dd>
-<dt><code>vboxnet1</code></dt><dd>Another Host-only network, simulating the tiny
-Ethernet between Gate and the campus Wi-Fi access point. It has no
+<dt><code>vboxnet1</code></dt><dd>Another Host-only network, simulating the untrusted
+Ethernet between Gate and the campus IoT (and Wi-Fi APs). It has no
services, no DHCP, just the host at <code>192.168.57.2</code>, simulating the
NATed Wi-Fi network.</dd>
</dl>
</p>
<div class="org-src-container">
-<pre class="src src-sh">VBoxManage natnetwork add --netname premises <span class="org-sh-escaped-newline">\</span>
+<pre class="src src-sh"><code>VBoxManage natnetwork add --netname premises <span class="org-sh-escaped-newline">\</span>
--network 192.168.15.0/24 <span class="org-sh-escaped-newline">\</span>
--enable --dhcp on --ipv6 off
VBoxManage natnetwork start --netname premises
VBoxManage dhcpserver modify --interface=vboxnet0 --disable
VBoxManage hostonlyif create <span class="org-comment-delimiter"># </span><span class="org-comment">vboxnet1</span>
VBoxManage hostonlyif ipconfig vboxnet1 --ip=192.168.57.2
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-org28b0352" class="outline-3">
-<h3 id="org28b0352"><span class="section-number-3">13.2.</span> The Test Machines</h3>
+<div id="outline-container-orgd7a9abd" class="outline-3">
+<h3 id="orgd7a9abd"><span class="section-number-3">13.2.</span> The Test Machines</h3>
<div class="outline-text-3" id="text-13-2">
<p>
The virtual machines are created by <code>VBoxManage</code> command lines in the
following sub-sections. They each start with a recent Debian release
(e.g. <q>debian-12.5.0-amd64-netinst.iso</q>) in their simulated DVD
-drives. As in <a href="#org754e9f1">The Hardware</a> preparation process being simulated, a few
-additional software packages are installed. Unlike in <a href="#org754e9f1">The Hardware</a>
+drives. As in <a href="#orgbf29081">The Hardware</a> preparation process being simulated, a few
+additional software packages are installed. Unlike in <a href="#orgbf29081">The Hardware</a>
preparation, machines are moved to their final networks and <i>then</i>
remote access is authorized. (They are not accessible via <code>ssh</code> on
the VirtualBox NAT network where they first boot.)
configuration by Ansible.
</p>
</div>
-<div id="outline-container-orgde4a074" class="outline-4">
-<h4 id="orgde4a074"><span class="section-number-4">13.2.1.</span> A Test Machine</h4>
+<div id="outline-container-org310a70b" class="outline-4">
+<h4 id="org310a70b"><span class="section-number-4">13.2.1.</span> A Test Machine</h4>
<div class="outline-text-4" id="text-13-2-1">
<p>
The following shell function contains most of the <code>VBoxManage</code>
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-keyword">function</span> <span class="org-function-name">create_vm</span> {
+<pre class="src src-sh"><code><span class="org-keyword">function</span> <span class="org-function-name">create_vm</span> {
VBoxManage createvm --name $<span class="org-variable-name">NAME</span> --ostype Debian_64 --register
VBoxManage modifyvm $<span class="org-variable-name">NAME</span> --memory $<span class="org-variable-name">RAM</span>
VBoxManage createhd --size $<span class="org-variable-name">DISK</span> <span class="org-sh-escaped-newline">\</span>
--port 0 --device 0 --type dvddrive --medium $<span class="org-variable-name">ISO</span>
VBoxManage modifyvm $<span class="org-variable-name">NAME</span> --boot1 dvd --boot2 disk
}
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-variable-name">NAME</span>=front
+<pre class="src src-sh"><code><span class="org-variable-name">NAME</span>=front
<span class="org-variable-name">RAM</span>=512
<span class="org-variable-name">DISK</span>=4096
<span class="org-variable-name">ISO</span>=~/Downloads/debian-12.5.0-amd64-netinst.iso
create_vm
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-org96e03aa" class="outline-4">
-<h4 id="org96e03aa"><span class="section-number-4">13.2.2.</span> The Test Front Machine</h4>
+<div id="outline-container-org28db7d4" class="outline-4">
+<h4 id="org28db7d4"><span class="section-number-4">13.2.2.</span> The Test Front Machine</h4>
<div class="outline-text-4" id="text-13-2-2">
<p>
The <code>front</code> machine is created with 512MiB of RAM, 4GiB of disk, and
its primary network interface moved to the simulated Internet, the NAT
network <code>premises</code>. <code>front</code> also gets a second network interface, on
the host-only network <code>vboxnet1</code>, to make it directly accessible to
-the administrator's notebook (as described in <a href="#org6e2b33d">The Test Networks</a>).
+the administrator's notebook (as described in <a href="#orgf8057e6">The Test Networks</a>).
</p>
<div class="org-src-container">
-<pre class="src src-sh">VBoxManage modifyvm front --nic1 natnetwork --natnetwork1 premises
+<pre class="src src-sh"><code>VBoxManage modifyvm front --nic1 natnetwork --natnetwork1 premises
VBoxManage modifyvm front --nic2 hostonly --hostonlyadapter2 vboxnet1
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<q>eth1</q><pre class="src src-conf">auto enp0s8
+<q>eth1</q><pre class="src src-conf"><code>auto enp0s8
iface enp0s8 inet static
address 192.168.57.3/24
-</pre>
+</code></pre>
</div>
<p>
deployed on a frontier, always in the cloud. Additional Debian
packages are assumed to be readily available. Thus Ansible installs
them as necessary, but first the administrator authorizes remote
-access by following the instructions in the final section: <a href="#orgc910086">Ansible
+access by following the instructions in the final section: <a href="#orgab73a63">Ansible
Test Authorization</a>.
</p>
</div>
</div>
-<div id="outline-container-org038abd9" class="outline-4">
-<h4 id="org038abd9"><span class="section-number-4">13.2.3.</span> The Test Gate Machine</h4>
+<div id="outline-container-org4da3a01" class="outline-4">
+<h4 id="org4da3a01"><span class="section-number-4">13.2.3.</span> The Test Gate Machine</h4>
<div class="outline-text-4" id="text-13-2-3">
<p>
The <code>gate</code> machine is created with the same amount of RAM and disk as
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-variable-name">NAME</span>=gate
+<pre class="src src-sh"><code><span class="org-variable-name">NAME</span>=gate
create_vm
-</pre>
+</code></pre>
</div>
<p>
-After Debian is installed (as detailed in <a href="#orgde4a074">A Test Machine</a>) and the
+After Debian is installed (as detailed in <a href="#org310a70b">A Test Machine</a>) and the
machine rebooted, the administrator logs in and installs several
additional software packages.
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo apt install netplan.io systemd-resolved unattended-upgrades <span class="org-sh-escaped-newline">\</span>
+<pre class="src src-sh"><code>sudo apt install netplan.io systemd-resolved unattended-upgrades <span class="org-sh-escaped-newline">\</span>
ufw isc-dhcp-server postfix openvpn
-</pre>
+</code></pre>
</div>
<p>
<p>
<code>gate</code> can then move to the campus. It is shut down before the
following <code>VBoxManage</code> commands are executed. The commands disconnect
-the primary Ethernet interface from <code>premises</code> and connected it to
-<code>vboxnet0</code>. They also create two new interfaces, <code>isp</code> and <code>wifi</code>,
+the primary Ethernet interface from <code>premises</code> and connect it to
+<code>vboxnet0</code>. They also create two new interfaces, <code>isp</code> and <code>wild</code>,
connected to the simulated ISP and campus wireless access point.
</p>
<div class="org-src-container">
-<pre class="src src-sh">VBoxManage modifyvm gate --mac-address1=080027f31679
+<pre class="src src-sh"><code>VBoxManage modifyvm gate --mac-address1=080027f31679
VBoxManage modifyvm gate --nic1 hostonly --hostonlyadapter1 vboxnet0
VBoxManage modifyvm gate --mac-address2=0800273d42e5
VBoxManage modifyvm gate --nic2 natnetwork --natnetwork2 premises
VBoxManage modifyvm gate --mac-address3=0800274aded2
VBoxManage modifyvm gate --nic3 hostonly --hostonlyadapter3 vboxnet1
-</pre>
+</code></pre>
</div>
<p>
<tr>
<td class="org-left"><code>enp0s9</code></td>
<td class="org-left"><code>vboxnet1</code></td>
-<td class="org-left">campus wireless</td>
-<td class="org-left"><code>gate_wifi_mac</code></td>
+<td class="org-left">campus IoT</td>
+<td class="org-left"><code>gate_wild_mac</code></td>
</tr>
</tbody>
</table>
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo ip address add 192.168.56.2/24 dev enp0s3
-</pre>
+<pre class="src src-sh"><code>sudo ip address add 192.168.56.2/24 dev enp0s3
+</code></pre>
</div>
<p>
Finally, the administrator authorizes remote access by following the
-instructions in the final section: <a href="#orgc910086">Ansible Test Authorization</a>.
+instructions in the final section: <a href="#orgab73a63">Ansible Test Authorization</a>.
</p>
</div>
</div>
-<div id="outline-container-org18f3c58" class="outline-4">
-<h4 id="org18f3c58"><span class="section-number-4">13.2.4.</span> The Test Core Machine</h4>
+<div id="outline-container-org1f40acc" class="outline-4">
+<h4 id="org1f40acc"><span class="section-number-4">13.2.4.</span> The Test Core Machine</h4>
<div class="outline-text-4" id="text-13-2-4">
<p>
The <code>core</code> machine is created with 1GiB of RAM and 6GiB of disk.
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-variable-name">NAME</span>=core
+<pre class="src src-sh"><code><span class="org-variable-name">NAME</span>=core
<span class="org-variable-name">RAM</span>=2048
<span class="org-variable-name">DISK</span>=6144
create_vm
-</pre>
+</code></pre>
</div>
<p>
-After Debian is installed (as detailed in <a href="#orgde4a074">A Test Machine</a>) and the
+After Debian is installed (as detailed in <a href="#org310a70b">A Test Machine</a>) and the
machine rebooted, the administrator logs in and installs several
additional software packages.
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo apt install netplan.io systemd-resolved unattended-upgrades <span class="org-sh-escaped-newline">\</span>
+<pre class="src src-sh"><code>sudo apt install netplan.io systemd-resolved unattended-upgrades <span class="org-sh-escaped-newline">\</span>
ntp isc-dhcp-server bind9 apache2 openvpn <span class="org-sh-escaped-newline">\</span>
postfix dovecot-imapd fetchmail expect rsync <span class="org-sh-escaped-newline">\</span>
gnupg
libapache2-mod-php
sudo apt install nagios4 monitoring-plugins-basic lm-sensors <span class="org-sh-escaped-newline">\</span>
nagios-nrpe-plugin
-</pre>
+</code></pre>
</div>
<p>
<li>System mail name: core.small.private</li>
</ul>
+<p>
+And domain name resolution may be broken after installing
+<code>systemd-resolved</code>. A reboot is often needed after the first <code>apt
+install</code> command above.
+</p>
+
<p>
Before shutting down, the name of the primary Ethernet interface
should be compared to the example variable setting in
</p>
<div class="org-src-container">
-<pre class="src src-sh">VBoxManage modifyvm core --nic1 hostonly --hostonlyadapter1 vboxnet0
-</pre>
+<pre class="src src-sh"><code>VBoxManage modifyvm core --nic1 hostonly --hostonlyadapter1 vboxnet0
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo ip address add 192.168.56.1/24 dev enp0s3
-</pre>
+<pre class="src src-sh"><code>sudo ip address add 192.168.56.1/24 dev enp0s3
+</code></pre>
</div>
<p>
Finally, the administrator authorizes remote access by following the
-instructions in the next section: <a href="#orgc910086">Ansible Test Authorization</a>.
+instructions in the next section: <a href="#orgab73a63">Ansible Test Authorization</a>.
</p>
</div>
</div>
-<div id="outline-container-orgc910086" class="outline-4">
-<h4 id="orgc910086"><span class="section-number-4">13.2.5.</span> Ansible Test Authorization</h4>
+<div id="outline-container-orgab73a63" class="outline-4">
+<h4 id="orgab73a63"><span class="section-number-4">13.2.5.</span> Ansible Test Authorization</h4>
<div class="outline-text-4" id="text-13-2-5">
<p>
To authorize Ansible's access to the three test machines, they must
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-variable-name">SRC</span>=Secret/ssh_admin/id_rsa.pub
+<pre class="src src-sh"><code><span class="org-variable-name">SRC</span>=Secret/ssh_admin/id_rsa.pub
scp $<span class="org-variable-name">SRC</span> sysadm@192.168.57.3:admin_key <span class="org-comment-delimiter"># </span><span class="org-comment">Front</span>
scp $<span class="org-variable-name">SRC</span> sysadm@192.168.56.2:admin_key <span class="org-comment-delimiter"># </span><span class="org-comment">Gate</span>
scp $<span class="org-variable-name">SRC</span> sysadm@192.168.56.1:admin_key <span class="org-comment-delimiter"># </span><span class="org-comment">Core</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">( <span class="org-builtin">cd</span>; <span class="org-builtin">umask</span> 077; mkdir .ssh; cp admin_key .ssh/authorized_keys )
-</pre>
+<pre class="src src-sh"><code>( <span class="org-builtin">cd</span>; <span class="org-builtin">umask</span> 077; mkdir .ssh; cp admin_key .ssh/authorized_keys )
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">scp Secret/ssh_front/etc/ssh/ssh_host_* sysadm@192.168.57.3:
-</pre>
+<pre class="src src-sh"><code>scp Secret/ssh_front/etc/ssh/ssh_host_* sysadm@192.168.57.3:
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">chmod 600 ssh_host_*
+<pre class="src src-sh"><code>chmod 600 ssh_host_*
chmod 644 ssh_host_*.pub
sudo cp -b ssh_host_* /etc/ssh/
-</pre>
+</code></pre>
</div>
<p>
</div>
</div>
</div>
-<div id="outline-container-org0e22649" class="outline-3">
-<h3 id="org0e22649"><span class="section-number-3">13.3.</span> Configure Test Machines</h3>
+<div id="outline-container-org870180a" class="outline-3">
+<h3 id="org870180a"><span class="section-number-3">13.3.</span> Configure Test Machines</h3>
<div class="outline-text-3" id="text-13-3">
<p>
At this point the three test machines <code>core</code>, <code>gate</code>, and <code>front</code> are
</p>
</div>
</div>
-<div id="outline-container-orge71084a" class="outline-3">
-<h3 id="orge71084a"><span class="section-number-3">13.4.</span> Test Basics</h3>
+<div id="outline-container-orga849e1c" class="outline-3">
+<h3 id="orga849e1c"><span class="section-number-3">13.4.</span> Test Basics</h3>
<div class="outline-text-3" id="text-13-4">
<p>
At this point the test institute is just <code>core</code>, <code>gate</code> and <code>front</code>,
</p>
<div class="org-src-container">
-<pre class="src src-sh">systemctl status
-</pre>
+<pre class="src src-sh"><code>systemctl status
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">ping -c 1 8.8.4.4 <span class="org-comment-delimiter"># </span><span class="org-comment">dns.google</span>
+<pre class="src src-sh"><code>ping -c 1 8.8.4.4 <span class="org-comment-delimiter"># </span><span class="org-comment">dns.google</span>
ping -c 1 192.168.15.5 <span class="org-comment-delimiter"># </span><span class="org-comment">front_addr</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">host dns.google
+<pre class="src src-sh"><code>host dns.google
host core.small.private
host www
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">/sbin/sendmail root
+<pre class="src src-sh"><code>/sbin/sendmail root
Testing email to root.
<span class="org-builtin">.</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-org626187b" class="outline-3">
-<h3 id="org626187b"><span class="section-number-3">13.5.</span> The Test Nextcloud</h3>
+<div id="outline-container-org560f2c4" class="outline-3">
+<h3 id="org560f2c4"><span class="section-number-3">13.5.</span> The Test Nextcloud</h3>
<div class="outline-text-3" id="text-13-5">
<p>
Further tests involve Nextcloud account management. Nextcloud is
-installed on <code>core</code> as described in <a href="#orgd97190a">Configure Nextcloud</a>. Once
+installed on <code>core</code> as described in <a href="#org640e4f7">Configure Nextcloud</a>. Once
<q>/Nextcloud/</q> is created, <code>./inst config core</code> will validate
or update its configuration files.
</p>
</p>
</div>
</div>
-<div id="outline-container-orgf1f2447" class="outline-3">
-<h3 id="orgf1f2447"><span class="section-number-3">13.6.</span> Test New Command</h3>
+<div id="outline-container-orgd08a549" class="outline-3">
+<h3 id="orgd08a549"><span class="section-number-3">13.6.</span> Test New Command</h3>
<div class="outline-text-3" id="text-13-6">
<p>
A member must be enrolled so that a member's client machine can be
</p>
<div class="org-src-container">
-<pre class="src src-sh">./inst new dick
-</pre>
+<pre class="src src-sh"><code>./inst new dick
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-orgc9c0613" class="outline-3">
-<h3 id="orgc9c0613"><span class="section-number-3">13.7.</span> The Test Member Notebook</h3>
+<div id="outline-container-orgdab6eef" class="outline-3">
+<h3 id="orgdab6eef"><span class="section-number-3">13.7.</span> The Test Member Notebook</h3>
<div class="outline-text-3" id="text-13-7">
<p>
A test member's notebook is created next, much like the servers,
</p>
<div class="org-src-container">
-<pre class="src src-sh"><span class="org-variable-name">NAME</span>=dick
+<pre class="src src-sh"><code><span class="org-variable-name">NAME</span>=dick
<span class="org-variable-name">RAM</span>=2048
<span class="org-variable-name">DISK</span>=8192
create_vm
VBoxManage modifyvm $<span class="org-variable-name">NAME</span> --macaddress1 080027dc54b5
VBoxManage modifyvm $<span class="org-variable-name">NAME</span> --nic1 hostonly --hostonlyadapter1 vboxnet1
-</pre>
+</code></pre>
</div>
<p>
</p>
<p>
-Debian is installed much as detailed in <a href="#orgde4a074">A Test Machine</a> <i>except</i> that
+Debian is installed much as detailed in <a href="#org310a70b">A Test Machine</a> <i>except</i> that
the SSH server option is <i>not</i> needed and the GNOME desktop option
<i>is</i>. When the machine reboots, the administrator logs into the
desktop and installs a couple additional software packages (which
</p>
<div class="org-src-container">
-<pre class="src src-nil">sudo apt install network-manager-openvpn-gnome \
+<pre class="src src-nil"><code>sudo apt install network-manager-openvpn-gnome \
openvpn-systemd-resolved \
nextcloud-desktop evolution
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgbaaca36" class="outline-3">
-<h3 id="orgbaaca36"><span class="section-number-3">13.8.</span> Test Client Command</h3>
+<div id="outline-container-orgec34fb6" class="outline-3">
+<h3 id="orgec34fb6"><span class="section-number-3">13.8.</span> Test Client Command</h3>
<div class="outline-text-3" id="text-13-8">
<p>
The <code>./inst client</code> command is used to issue keys for the institute's
</p>
<div class="org-src-container">
-<pre class="src src-sh">./inst client debian dick dick
-</pre>
+<pre class="src src-sh"><code>./inst client debian dick dick
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-orgefe17f8" class="outline-3">
-<h3 id="orgefe17f8"><span class="section-number-3">13.9.</span> Test Campus VPN</h3>
+<div id="outline-container-org788a72a" class="outline-3">
+<h3 id="org788a72a"><span class="section-number-3">13.9.</span> Test Campus VPN</h3>
<div class="outline-text-3" id="text-13-9">
<p>
-The <q>campus.ovpn</q> OpenVPN configuration file (generated in <a href="#orgbaaca36">Test Client
+The <q>campus.ovpn</q> OpenVPN configuration file (generated in <a href="#orgec34fb6">Test Client
Command</a>) is transferred to <code>dick</code>, which is at the Wi-Fi access
point's <code>wifi_wan_addr</code>.
</p>
<div class="org-src-container">
-<pre class="src src-sh">scp *.ovpn sysadm@192.168.57.2:
-</pre>
+<pre class="src src-sh"><code>scp *.ovpn sysadm@192.168.57.2:
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">systemctl status
+<pre class="src src-sh"><code>systemctl status
ping -c 1 8.8.4.4 <span class="org-comment-delimiter"># </span><span class="org-comment">dns.google</span>
ping -c 1 192.168.56.1 <span class="org-comment-delimiter"># </span><span class="org-comment">core</span>
host dns.google
host core.small.private
host www
-</pre>
+</code></pre>
</div>
</div>
</div>
-<div id="outline-container-org861e789" class="outline-3">
-<h3 id="org861e789"><span class="section-number-3">13.10.</span> Test Web Pages</h3>
+<div id="outline-container-org6342178" class="outline-3">
+<h3 id="org6342178"><span class="section-number-3">13.10.</span> Test Web Pages</h3>
<div class="outline-text-3" id="text-13-10">
<p>
Next, the administrator copies <a href="Backup/WWW/"><q>Backup/WWW/</q></a> (included in the
</p>
<div class="org-src-container">
-<pre class="src src-sh">sudo chown -R sysadm.staff /WWW/campus
+<pre class="src src-sh"><code>sudo chown -R sysadm.staff /WWW/campus
sudo chown -R monkey.staff /WWW/live /WWW/test
sudo chmod 02775 /WWW/*
sudo chmod 664 /WWW/*/index.html
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-orgbe2a118" class="outline-3">
-<h3 id="orgbe2a118"><span class="section-number-3">13.11.</span> Test Web Update</h3>
+<div id="outline-container-org9931f74" class="outline-3">
+<h3 id="org9931f74"><span class="section-number-3">13.11.</span> Test Web Update</h3>
<div class="outline-text-3" id="text-13-11">
<p>
Modify <q>/WWW/live/index.html</q> on <code>core</code> and wait 15 minutes for it to
</p>
</div>
</div>
-<div id="outline-container-org11876cb" class="outline-3">
-<h3 id="org11876cb"><span class="section-number-3">13.12.</span> Test Nextcloud</h3>
+<div id="outline-container-org0145aad" class="outline-3">
+<h3 id="org0145aad"><span class="section-number-3">13.12.</span> Test Nextcloud</h3>
<div class="outline-text-3" id="text-13-12">
<p>
Nextcloud is typically installed and configured <i>after</i> the first
installation directory <q>/Nextcloud/nextcloud/</q> appears, the Ansible
code skips parts of the Nextcloud configuration. The same
installation (or restoration) process used on Core is used on <code>core</code>
-to create <q>/Nextcloud/</q>. The process starts with <a href="#org45a4a2a">Create
-<q>/Nextcloud/</q></a>, involves <a href="#org0568172">Restore Nextcloud</a> or <a href="#orga610911">Install Nextcloud</a>,
-and runs <code>./inst config core</code> again <a href="#org380598a">8.23.6</a>. When the <code>./inst
+to create <q>/Nextcloud/</q>. The process starts with <a href="#orgdb3439f">Create
+<q>/Nextcloud/</q></a>, involves <a href="#org3c8ed7b">Restore Nextcloud</a> or <a href="#orgb7a7660">Install Nextcloud</a>,
+and runs <code>./inst config core</code> again <a href="#orgdc9a64a">8.23.6</a>. When the <code>./inst
config core</code> command is happy with the Nextcloud configuration on
<code>core</code>, the administrator uses Dick's notebook to test it, performing
the following tests on <code>dick</code>'s desktop.
<li>Use a web browser to get <code>http://core/nextcloud/</code>. It should be a
warning about accessing Nextcloud by an untrusted name.</li>
-<li>Get <code>http://core.small.private/nextcloud/</code>. It should be a
+<li>Get <code>https://core.small.private/nextcloud/</code>. It should be a
login web page.</li>
<li>Login as <code>sysadm</code> with password <code>fubar</code>.</li>
<li>Use the Nextcloud app to sync <q>~/nextCloud/</q> with the cloud. In the
Nextcloud app's Connection Wizard (the initial dialog), choose to
"Log in to your Nextcloud" with the URL
-<code>http://core.small.private/nextcloud</code>. The web browser should pop
+<code>https://core.small.private/nextcloud</code>. The web browser should pop
up with a new tab: "Connect to your account". Press "Log in" and
"Grant access". The Nextcloud Connection Wizard then prompts for
sync parameters. The defaults are fine. Presumably the Local
<li>Create a CardDAV account in Evolution. Choose Edit, Accounts, Add,
Address Book, Type CardDAV, name Small Institute, and user <code>dick</code>.
-The URL starts with <code>http://core.small.private/nextcloud/</code> and
+The URL starts with <code>https://core.small.private/nextcloud/</code> and
ends with <code>remote.php/dav/addressbooks/users/dick/contacts/</code> (yeah,
88 characters!). Create a contact in the new address book and see
it in the Contacts web page. At some point Evolution will need
</ul>
</div>
</div>
-<div id="outline-container-org10daf29" class="outline-3">
-<h3 id="org10daf29"><span class="section-number-3">13.13.</span> Test Email</h3>
+<div id="outline-container-org89efb80" class="outline-3">
+<h3 id="org89efb80"><span class="section-number-3">13.13.</span> Test Email</h3>
<div class="outline-text-3" id="text-13-13">
<p>
With Evolution running on the member notebook <code>dick</code>, one second email
</p>
<div class="org-src-container">
-<pre class="src src-sh">/sbin/sendmail dick
+<pre class="src src-sh"><code>/sbin/sendmail dick
Subject: Hello, Dick.
How are you?
<span class="org-builtin">.</span>
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-orgcb10c33" class="outline-3">
-<h3 id="orgcb10c33"><span class="section-number-3">13.14.</span> Test Public VPN</h3>
+<div id="outline-container-orgd3f059a" class="outline-3">
+<h3 id="orgd3f059a"><span class="section-number-3">13.14.</span> Test Public VPN</h3>
<div class="outline-text-3" id="text-13-14">
<p>
At this point, <code>dick</code> can move abroad, from the campus Wi-Fi
</p>
<div class="org-src-container">
-<pre class="src src-s">VBoxManage modifyvm dick --nic1 natnetwork --natnetwork1 premises
-</pre>
+<pre class="src src-s"><code>VBoxManage modifyvm dick --nic1 natnetwork --natnetwork1 premises
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">ping -c 1 8.8.4.4 <span class="org-comment-delimiter"># </span><span class="org-comment">dns.google</span>
+<pre class="src src-sh"><code>ping -c 1 8.8.4.4 <span class="org-comment-delimiter"># </span><span class="org-comment">dns.google</span>
ping -c 1 192.168.56.1 <span class="org-comment-delimiter"># </span><span class="org-comment">core</span>
host dns.google
host core.small.private
host www
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-org4ecdc5b" class="outline-3">
-<h3 id="org4ecdc5b"><span class="section-number-3">13.15.</span> Test Pass Command</h3>
+<div id="outline-container-org1fd1f8b" class="outline-3">
+<h3 id="org1fd1f8b"><span class="section-number-3">13.15.</span> Test Pass Command</h3>
<div class="outline-text-3" id="text-13-15">
<p>
To test the <code>./inst pass</code> command, the administrator logs in to <code>core</code>
</p>
<div class="org-src-container">
-<pre class="src src-sh">( <span class="org-builtin">cd</span> ~/Maildir/new/
+<pre class="src src-sh"><code>( <span class="org-builtin">cd</span> ~/Maildir/new/
cp <span class="org-sh-quoted-exec">`ls -1t | head -1`</span> ~/msg )
grep Subject: ~/msg
-</pre>
+</code></pre>
</div>
<p>
</p>
<div class="org-src-container">
-<pre class="src src-sh">scp sysadm@192.168.56.1:msg ./
+<pre class="src src-sh"><code>scp sysadm@192.168.56.1:msg ./
./inst pass < msg
-</pre>
+</code></pre>
</div>
<p>
</p>
</div>
</div>
-<div id="outline-container-org37b7a4b" class="outline-3">
-<h3 id="org37b7a4b"><span class="section-number-3">13.16.</span> Test Old Command</h3>
+<div id="outline-container-org567770b" class="outline-3">
+<h3 id="org567770b"><span class="section-number-3">13.16.</span> Test Old Command</h3>
<div class="outline-text-3" id="text-13-16">
<p>
One more institute command is left to exercise. The administrator
</p>
<div class="org-src-container">
-<pre class="src src-sh">./inst old dick
-</pre>
+<pre class="src src-sh"><code>./inst old dick
+</code></pre>
</div>
<p>
</div>
</div>
</div>
-<div id="outline-container-orgd49e21c" class="outline-2">
-<h2 id="orgd49e21c"><span class="section-number-2">14.</span> Future Work</h2>
+<div id="outline-container-orgf6f9793" class="outline-2">
+<h2 id="orgf6f9793"><span class="section-number-2">14.</span> Future Work</h2>
<div class="outline-text-2" id="text-14">
<p>
The small institute's network, as currently defined in this doocument,
is lacking in a number of respects.
</p>
</div>
-<div id="outline-container-org25c0257" class="outline-3">
-<h3 id="org25c0257"><span class="section-number-3">14.1.</span> Deficiencies</h3>
+<div id="outline-container-org26639c5" class="outline-3">
+<h3 id="org26639c5"><span class="section-number-3">14.1.</span> Deficiencies</h3>
<div class="outline-text-3" id="text-14-1">
<p>
The current network monitoring is rudimentary. It could use some
separate certificates for Gate and Front? Use the same certificate
and key on Gate and Front?
</p>
-
-<p>
-Nextcloud should really be found at <code>https://CLOUD.small.private/</code>
-rather than <code>https://core.small.private/nextcloud/</code>, to ease
-future expansion (moving services to additional machines).
-</p>
-
-<p>
-HTTPS could be used for Nextcloud transactions even though they are
-carried on encrypted VPNs. This would eliminate a big warning on the
-Nextcloud Administration Overview page.
-</p>
</div>
</div>
-<div id="outline-container-org252a7b9" class="outline-3">
-<h3 id="org252a7b9"><span class="section-number-3">14.2.</span> More Tests</h3>
+<div id="outline-container-orgfe73858" class="outline-3">
+<h3 id="orgfe73858"><span class="section-number-3">14.2.</span> More Tests</h3>
<div class="outline-text-3" id="text-14-2">
<p>
The testing process described in the previous chapter is far from
complete. Additional tests are needed.
</p>
</div>
-<div id="outline-container-orgf7d014e" class="outline-4">
-<h4 id="orgf7d014e"><span class="section-number-4">14.2.1.</span> Backup</h4>
+<div id="outline-container-orgc61d0e9" class="outline-4">
+<h4 id="orgc61d0e9"><span class="section-number-4">14.2.1.</span> Backup</h4>
<div class="outline-text-4" id="text-14-2-1">
<p>
The <code>backup</code> command has not been tested. It needs an encrypted
</p>
</div>
</div>
-<div id="outline-container-org2053b4a" class="outline-4">
-<h4 id="org2053b4a"><span class="section-number-4">14.2.2.</span> Restore</h4>
+<div id="outline-container-org6d144a5" class="outline-4">
+<h4 id="org6d144a5"><span class="section-number-4">14.2.2.</span> Restore</h4>
<div class="outline-text-4" id="text-14-2-2">
<p>
The restore process has not been tested. It might just copy <a href="Backup/"><q>Backup/</q></a>
</p>
</div>
</div>
-<div id="outline-container-org262e2b2" class="outline-4">
-<h4 id="org262e2b2"><span class="section-number-4">14.2.3.</span> Campus Disconnect</h4>
+<div id="outline-container-org876c9cb" class="outline-4">
+<h4 id="org876c9cb"><span class="section-number-4">14.2.3.</span> Campus Disconnect</h4>
<div class="outline-text-4" id="text-14-2-3">
<p>
Email access (IMAPS) on <code>front</code> is… difficult to test unless
</div>
</div>
</div>
-<div id="outline-container-orge6607e3" class="outline-2">
-<h2 id="orge6607e3"><span class="section-number-2">15.</span> Appendix: The Bootstrap</h2>
+<div id="outline-container-orgb988f90" class="outline-2">
+<h2 id="orgb988f90"><span class="section-number-2">15.</span> Appendix: The Bootstrap</h2>
<div class="outline-text-2" id="text-15">
<p>
Creating the private network from whole cloth (machines with recent
get to the additional packages.
</p>
</div>
-<div id="outline-container-orgc34cb28" class="outline-3">
-<h3 id="orgc34cb28"><span class="section-number-3">15.1.</span> The Current Strategy</h3>
+<div id="outline-container-org7fe37c6" class="outline-3">
+<h3 id="org7fe37c6"><span class="section-number-3">15.1.</span> The Current Strategy</h3>
<div class="outline-text-3" id="text-15-1">
<p>
-The strategy pursued in <a href="#org754e9f1">The Hardware</a> is two phase: prepare the servers
+The strategy pursued in <a href="#orgbf29081">The Hardware</a> is two phase: prepare the servers
on the Internet where additional packages are accessible, then connect
them to the campus facilities (the private Ethernet switch, Wi-Fi AP,
ISP), manually configure IP addresses (while the DHCP client silently
</p>
</div>
</div>
-<div id="outline-container-org11fbf4b" class="outline-3">
-<h3 id="org11fbf4b"><span class="section-number-3">15.2.</span> Starting With Gate</h3>
+<div id="outline-container-org94b8b56" class="outline-3">
+<h3 id="org94b8b56"><span class="section-number-3">15.2.</span> Starting With Gate</h3>
<div class="outline-text-3" id="text-15-2">
<p>
The strategy of Starting With Gate concentrates on configuring Gate's
</ul>
</div>
</div>
-<div id="outline-container-org679fbc3" class="outline-3">
-<h3 id="org679fbc3"><span class="section-number-3">15.3.</span> Pre-provision With Ansible</h3>
+<div id="outline-container-org1c34ede" class="outline-3">
+<h3 id="org1c34ede"><span class="section-number-3">15.3.</span> Pre-provision With Ansible</h3>
<div class="outline-text-3" id="text-15-3">
<p>
A refinement of the current strategy might avoid the need to maintain
</div></div>
<div id="postamble" class="status">
<p class="author">Author: Matt Birkholz</p>
-<p class="date">Created: 2024-10-29 Tue 21:35</p>
+<p class="date">Created: 2025-05-31 Sat 22:27</p>
<p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>