Update README.html, after fixing core/files/ src block to mkdirp.
authorMatt Birkholz <matt@birchwood-abbey.net>
Sat, 9 Mar 2024 16:37:29 +0000 (10:37 -0600)
committerMatt Birkholz <matt@birchwood-abbey.net>
Sat, 9 Mar 2024 16:37:29 +0000 (10:37 -0600)
README.html
README.org

index 8ca8ec57493ddb50732aa74989c9ffe9dfc06052..fd9a8efaa5d979d8557852c4610f5df2ab38d9dc 100644 (file)
@@ -3,7 +3,7 @@
 "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-02-26 Mon 21:58 -->
+<!-- 2024-03-09 Sat 10:34 -->
 <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>
@@ -48,7 +48,7 @@ connects to Front making the institute email, cloud, etc. available to
 members off campus.
 </p>
 
-<pre class="example" id="org08ed86c">
+<pre class="example" id="org908d63b">
                 =                                                   
               _|||_                                                 
         =-The-Institute-=                                           
@@ -1030,7 +1030,7 @@ example result follows the code.
 </pre>
 </div>
 
-<div class="TEXT" id="org6d1f744">
+<div class="TEXT" id="orgb05406e">
 <p>
 =&gt; 10.62.17.0/24
 </p>
@@ -1483,7 +1483,7 @@ USB-Ethernet adapter, or a wireless adapter connected to a
 campground Wi-Fi access point, etc.</li>
 </ol>
 
-<pre class="example" id="org9575410">
+<pre class="example" id="org9215090">
 =============== | ==================================================
                 |                                           Premises
           (Campus ISP)                                              
@@ -1506,7 +1506,7 @@ This avoids the need for a second Wi-Fi access point and leads to the
 following topology.
 </p>
 
-<pre class="example" id="org1a67bf1">
+<pre class="example" id="org451080a">
 =============== | ==================================================
                 |                                           Premises
            (House ISP)                                              
@@ -1659,8 +1659,8 @@ 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-orga320cc8" class="outline-3">
-<h3 id="orga320cc8"><span class="section-number-3">6.1.</span> Include Particulars</h3>
+<div id="outline-container-org6c2f99f" class="outline-3">
+<h3 id="org6c2f99f"><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
@@ -1801,8 +1801,8 @@ uses the institute's CA and server certificates, and expects client
 certificates signed by the institute CA.
 </p>
 </div>
-<div id="outline-container-orga652c4f" class="outline-3">
-<h3 id="orga652c4f"><span class="section-number-3">7.1.</span> Include Particulars</h3>
+<div id="outline-container-org61196f1" class="outline-3">
+<h3 id="org61196f1"><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
@@ -1827,8 +1827,8 @@ membership roll, so these are included was well.
 </div>
 </div>
 </div>
-<div id="outline-container-orgd3bbfbb" class="outline-3">
-<h3 id="orgd3bbfbb"><span class="section-number-3">7.2.</span> Configure Hostname</h3>
+<div id="outline-container-orgf305da5" class="outline-3">
+<h3 id="orgf305da5"><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
@@ -1858,8 +1858,8 @@ delivery.
 </div>
 </div>
 </div>
-<div id="outline-container-org41f6c57" class="outline-3">
-<h3 id="org41f6c57"><span class="section-number-3">7.3.</span> Add Administrator to System Groups</h3>
+<div id="outline-container-org2e0d608" class="outline-3">
+<h3 id="org2e0d608"><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
@@ -1918,8 +1918,8 @@ those stored in <a href="Secret/ssh_front/etc/ssh/"><q>Secret/ssh_front/etc/ssh/
 </div>
 </div>
 </div>
-<div id="outline-container-org14610e1" class="outline-3">
-<h3 id="org14610e1"><span class="section-number-3">7.5.</span> Configure Monkey</h3>
+<div id="outline-container-orgb71ce41" class="outline-3">
+<h3 id="orgb71ce41"><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
@@ -1975,8 +1975,8 @@ Monkey uses Rsync to keep the institute's public web site up-to-date.
 </div>
 </div>
 </div>
-<div id="outline-container-org8cd2060" class="outline-3">
-<h3 id="org8cd2060"><span class="section-number-3">7.7.</span> Install Unattended Upgrades</h3>
+<div id="outline-container-orge5a6f0f" class="outline-3">
+<h3 id="orge5a6f0f"><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.
@@ -1991,8 +1991,8 @@ The institute prefers to install security updates as soon as possible.
 </div>
 </div>
 </div>
-<div id="outline-container-org4c79c93" class="outline-3">
-<h3 id="org4c79c93"><span class="section-number-3">7.8.</span> Configure User Accounts</h3>
+<div id="outline-container-org3da9c14" class="outline-3">
+<h3 id="org3da9c14"><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
@@ -2035,8 +2035,8 @@ recipient" replies.  The <a href="#orge7fe793">Account Management</a> chapter de
 </div>
 </div>
 </div>
-<div id="outline-container-orge91063f" class="outline-3">
-<h3 id="orge91063f"><span class="section-number-3">7.9.</span> Install Server Certificate</h3>
+<div id="outline-container-org9e626f9" class="outline-3">
+<h3 id="org9e626f9"><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
@@ -2154,27 +2154,13 @@ Debian default for <code>inet_interfaces</code>.
 <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 }
 - { p: smtpd_tls_key_file, v: /etc/server.key }
-- p: mynetworks
-  v: &gt;-
-     {{ 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
-- p: smtpd_recipient_restrictions
-  v: &gt;-
-     permit_mynetworks
-     reject_unauth_pipelining
-     reject_unauth_destination
-     reject_unknown_sender_domain
-- p: smtpd_relay_restrictions
-  v: permit_mynetworks reject_unauth_destination
-- { p: message_size_limit, v: 104857600 }
-- { p: delay_warning_time, v: 1h }
-- { p: maximal_queue_lifetime, v: 4h }
-- { p: bounce_queue_lifetime, v: 4h }
-- { p: home_mailbox, v: Maildir/ }
-- p: smtp_header_checks
-  v: regexp:/etc/postfix/header_checks.cf
+&lt;&lt;postfix-front-networks&gt;&gt;
+&lt;&lt;postfix-front-restrictions&gt;&gt;
+&lt;&lt;postfix-relaying&gt;&gt;
+&lt;&lt;postfix-message-size&gt;&gt;
+&lt;&lt;postfix-queue-times&gt;&gt;
+&lt;&lt;postfix-maildir&gt;&gt;
+&lt;&lt;postfix-header-checks&gt;&gt;
 </pre>
 </div>
 
@@ -2197,37 +2183,14 @@ start and enable the service.
     regexp: <span class="org-string">"^ *{{ item.p }} *="</span>
     line: <span class="org-string">"{{ item.p }} = {{ item.v }}"</span>
   loop:
-  - { p: smtpd_tls_cert_file, v: /etc/server.crt }
-  - { p: smtpd_tls_key_file, v: /etc/server.key }
-  - p: mynetworks
-    v: &gt;-
-       {{ 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
-  - p: smtpd_recipient_restrictions
-    v: &gt;-
-       permit_mynetworks
-       reject_unauth_pipelining
-       reject_unauth_destination
-       reject_unknown_sender_domain
-  - p: smtpd_relay_restrictions
-    v: permit_mynetworks reject_unauth_destination
-  - { p: message_size_limit, v: 104857600 }
-  - { p: delay_warning_time, v: 1h }
-  - { p: maximal_queue_lifetime, v: 4h }
-  - { p: bounce_queue_lifetime, v: 4h }
-  - { p: home_mailbox, v: Maildir/ }
-  - p: smtp_header_checks
-    v: regexp:/etc/postfix/header_checks.cf
+  &lt;&lt;postfix-front&gt;&gt;
   notify: Restart Postfix.
 
 - name: Install Postfix header_checks.
   become: yes
   copy:
     content: |
-      /^Received:/      IGNORE
-      /^User-Agent:/    IGNORE
+      &lt;&lt;postfix-header-checks-content&gt;&gt;
     dest: /etc/postfix/header_checks.cf
   notify: Postmap header checks.
 
@@ -2300,8 +2263,8 @@ created by a more specialized role.
 </div>
 </div>
 </div>
-<div id="outline-container-org0b2a149" class="outline-3">
-<h3 id="org0b2a149"><span class="section-number-3">7.12.</span> Configure Dovecot IMAPd</h3>
+<div id="outline-container-orgc70152d" class="outline-3">
+<h3 id="orgc70152d"><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
@@ -2338,16 +2301,11 @@ and enables it to start at every reboot.
   become: yes
   copy:
     content: |
-      <span class="org-variable-name">protocols</span> = imap
-      <span class="org-variable-name">ssl</span> = required
+      &lt;&lt;dovecot-tls&gt;&gt;
       <span class="org-variable-name">ssl_cert</span> = &lt;/etc/server.crt
       <span class="org-variable-name">ssl_key</span> = &lt;/etc/server.key
-      <span class="org-type">service imap-login</span> {
-        <span class="org-type">inet_listener imap</span> {
-          <span class="org-variable-name">port</span> = 0
-        }
-      }
-      <span class="org-variable-name">mail_location</span> = maildir:~/Maildir
+      &lt;&lt;dovecot-ports&gt;&gt;
+      &lt;&lt;dovecot-maildir&gt;&gt;
     dest: /etc/dovecot/local.conf
   notify: Restart Dovecot.
 
@@ -2457,12 +2415,9 @@ below create or remove the symbolic links.
 
 <p>
 The following are the necessary Apache2 directives: a <code>UserDir</code>
-directive naming <q>/home/www-users/</q>, a matching <code>Directory</code> block that
-allows the server to follow the symbol links, and a <code>Directory</code> block
-that matches the user directories and includes the standard <code>Require</code>
-and <code>AllowOverride</code> directives used on all of the institute's static
-web sites (<code>https://small.example.org/</code>, <code>http://live/</code>, and
-<code>http://test/</code>).
+directive naming <q>/home/www-users/</q> and matching <code>Directory</code> block
+that includes the standard <code>Require</code> and <code>AllowOverride</code> directives
+used on all of the institute's web sites.
 </p>
 
 <div class="org-src-container">
@@ -2474,12 +2429,6 @@ web sites (<code>https://small.example.org/</code>, <code>http://live/</code>, a
 </pre>
 </div>
 
-<div class="org-src-container">
-<code>apache-userdir-directory</code><pre class="src src-conf" id="org37c9c6d">Require all granted
-AllowOverride None
-</pre>
-</div>
-
 <p>
 The institute requires the use of HTTPS on Front, so its default HTTP
 virtual host permanently redirects requests to their corresponding
@@ -2508,7 +2457,7 @@ The <code>DocumentRoot</code> directive is accompanied by a <code>Directory</cod
 that authorizes access to the tree, and ensures <q>.htaccess</q> files
 within the tree are disabled for speed and security.  This and most of
 Front's Apache2 directives (below) are intended for the top level, not
-inside a <code>VirtualHost</code> block, to apply globally.
+the inside of a <code>VirtualHost</code> block.  They should apply globally.
 </p>
 
 <div class="org-src-container">
@@ -2521,18 +2470,12 @@ DocumentRoot /home/www
         AllowOverride None
 &lt;/Directory&gt;
 
-UserDir /home/www-users
-&lt;Directory /home/www-users/&gt;
-        Require all granted
-        AllowOverride None
-&lt;/Directory&gt;
+&lt;&lt;apache-userdir-front&gt;&gt;
 
 ErrorLog ${APACHE_LOG_DIR}/error.log
 CustomLog ${APACHE_LOG_DIR}/access.log combined
 
-&lt;VirtualHost *:80&gt;
-        Redirect permanent / https://{{ domain_name }}/
-&lt;/VirtualHost&gt;
+&lt;&lt;apache-redirect-front&gt;&gt;
 
 &lt;VirtualHost *:443&gt;
         SSLEngine on
@@ -2542,36 +2485,7 @@ CustomLog ${APACHE_LOG_DIR}/access.log combined
             /etc/apache2/sites-available/{{ domain_name }}-vhost.conf
 &lt;/VirtualHost&gt;
 
-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">'ECDHE-ECDSA-AES128-SHA'</span>,
-                    <span class="org-string">'ECDHE-ECDSA-AES256-SHA'</span>,
-                    <span class="org-string">'ECDHE-ECDSA-AES128-SHA256'</span>,
-                    <span class="org-string">'ECDHE-ECDSA-AES256-SHA384'</span>,
-                    <span class="org-string">'ECDHE-RSA-AES128-GCM-SHA256'</span>,
-                    <span class="org-string">'ECDHE-RSA-AES256-GCM-SHA384'</span>,
-                    <span class="org-string">'ECDHE-RSA-AES128-SHA'</span>,
-                    <span class="org-string">'ECDHE-RSA-AES256-SHA'</span>,
-                    <span class="org-string">'ECDHE-RSA-AES128-SHA256'</span>,
-                    <span class="org-string">'ECDHE-RSA-AES256-SHA384'</span>,
-                    <span class="org-string">'DHE-RSA-AES128-GCM-SHA256'</span>,
-                    <span class="org-string">'DHE-RSA-AES256-GCM-SHA384'</span>,
-                    <span class="org-string">'DHE-RSA-AES128-SHA'</span>,
-                    <span class="org-string">'DHE-RSA-AES256-SHA'</span>,
-                    <span class="org-string">'DHE-RSA-AES128-SHA256'</span>,
-                    <span class="org-string">'DHE-RSA-AES256-SHA256'</span>,
-                    <span class="org-string">'!aNULL'</span>,
-                    <span class="org-string">'!eNULL'</span>,
-                    <span class="org-string">'!LOW'</span>,
-                    <span class="org-string">'!3DES'</span>,
-                    <span class="org-string">'!MD5'</span>,
-                    <span class="org-string">'!EXP'</span>,
-                    <span class="org-string">'!PSK'</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>) }}
+&lt;&lt;apache-ciphers&gt;&gt;
 </pre>
 </div>
 
@@ -2606,66 +2520,7 @@ e.g. <q>/etc/apache2/sites-available/small.example.org.conf</q> and runs
   become: yes
   copy:
     content: |
-      ServerName {{ domain_name }}
-      ServerAdmin webmaster@{{ domain_name }}
-
-      DocumentRoot /home/www
-      &lt;Directory /home/www/&gt;
-        Require all granted
-        AllowOverride None
-      &lt;/Directory&gt;
-
-      UserDir /home/www-users
-      &lt;Directory /home/www-users/&gt;
-        Require all granted
-        AllowOverride None
-      &lt;/Directory&gt;
-
-      ErrorLog ${APACHE_LOG_DIR}/error.log
-      CustomLog ${APACHE_LOG_DIR}/access.log combined
-
-      &lt;VirtualHost *:80&gt;
-        Redirect permanent / https://{{ domain_name }}/
-      &lt;/VirtualHost&gt;
-
-      &lt;VirtualHost *:443&gt;
-        SSLEngine on
-        SSLCertificateFile /etc/server.crt
-        SSLCertificateKeyFile /etc/server.key
-        IncludeOptional \
-            /etc/apache2/sites-available/{{ domain_name }}-vhost.conf
-      &lt;/VirtualHost&gt;
-
-      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">'ECDHE-ECDSA-AES128-SHA'</span>,
-                          <span class="org-string">'ECDHE-ECDSA-AES256-SHA'</span>,
-                          <span class="org-string">'ECDHE-ECDSA-AES128-SHA256'</span>,
-                          <span class="org-string">'ECDHE-ECDSA-AES256-SHA384'</span>,
-                          <span class="org-string">'ECDHE-RSA-AES128-GCM-SHA256'</span>,
-                          <span class="org-string">'ECDHE-RSA-AES256-GCM-SHA384'</span>,
-                          <span class="org-string">'ECDHE-RSA-AES128-SHA'</span>,
-                          <span class="org-string">'ECDHE-RSA-AES256-SHA'</span>,
-                          <span class="org-string">'ECDHE-RSA-AES128-SHA256'</span>,
-                          <span class="org-string">'ECDHE-RSA-AES256-SHA384'</span>,
-                          <span class="org-string">'DHE-RSA-AES128-GCM-SHA256'</span>,
-                          <span class="org-string">'DHE-RSA-AES256-GCM-SHA384'</span>,
-                          <span class="org-string">'DHE-RSA-AES128-SHA'</span>,
-                          <span class="org-string">'DHE-RSA-AES256-SHA'</span>,
-                          <span class="org-string">'DHE-RSA-AES128-SHA256'</span>,
-                          <span class="org-string">'DHE-RSA-AES256-SHA256'</span>,
-                          <span class="org-string">'!aNULL'</span>,
-                          <span class="org-string">'!eNULL'</span>,
-                          <span class="org-string">'!LOW'</span>,
-                          <span class="org-string">'!3DES'</span>,
-                          <span class="org-string">'!MD5'</span>,
-                          <span class="org-string">'!EXP'</span>,
-                          <span class="org-string">'!PSK'</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>) }}
+      &lt;&lt;apache-front&gt;&gt;
     dest: /etc/apache2/sites-available/{{ domain_name }}.conf
   notify: Restart Apache2.
 
@@ -2765,8 +2620,8 @@ the users' <q>~/Public/HTML/</q> directories.
 </div>
 </div>
 </div>
-<div id="outline-container-org0fb006b" class="outline-3">
-<h3 id="org0fb006b"><span class="section-number-3">7.14.</span> Configure OpenVPN</h3>
+<div id="outline-container-org6af4461" class="outline-3">
+<h3 id="org6af4461"><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
@@ -2812,27 +2667,14 @@ and the common options discussed in <a href="#orgc2baf19">The VPN Service</a>.
 <div class="org-src-container">
 <code>openvpn-front</code><pre class="src src-conf" id="orgc467eda">server {{ public_vpn_net_and_mask }}
 client-config-dir /etc/openvpn/ccd
-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>
-dev-type tun
-dev ovpn
-topology subnet
-client-to-client
-keepalive 10 120
-push <span class="org-string">"dhcp-option DOMAIN {{ domain_priv }}"</span>
-push <span class="org-string">"dhcp-option DNS {{ core_addr }}"</span>
-user nobody
-group nogroup
-persist-key
-persist-tun
-cipher AES-256-GCM
-auth SHA256
-max-clients 20
-ifconfig-pool-persist ipp.txt
-status openvpn-status.log
-verb 3
+&lt;&lt;openvpn-front-routes&gt;&gt;
+&lt;&lt;openvpn-dev-mode&gt;&gt;
+&lt;&lt;openvpn-keepalive&gt;&gt;
+&lt;&lt;openvpn-dns&gt;&gt;
+&lt;&lt;openvpn-drop-priv&gt;&gt;
+&lt;&lt;openvpn-crypt&gt;&gt;
+&lt;&lt;openvpn-max&gt;&gt;
+&lt;&lt;openvpn-debug&gt;&gt;
 ca /usr/local/share/ca-certificates/{{ domain_name }}.crt
 cert server.crt
 key server.key
@@ -2870,8 +2712,7 @@ configure the OpenVPN server on Front.
   become: yes
   copy:
     content: |
-      iroute {{ private_net_and_mask }}
-      iroute {{ campus_vpn_net_and_mask }}
+      &lt;&lt;openvpn-ccd-core&gt;&gt;
     dest: /etc/openvpn/ccd/core
   notify: Restart OpenVPN.
 
@@ -2911,34 +2752,7 @@ configure the OpenVPN server on Front.
   become: yes
   copy:
     content: |
-      server {{ public_vpn_net_and_mask }}
-      client-config-dir /etc/openvpn/ccd
-      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>
-      dev-type tun
-      dev ovpn
-      topology subnet
-      client-to-client
-      keepalive 10 120
-      push <span class="org-string">"dhcp-option DOMAIN {{ domain_priv }}"</span>
-      push <span class="org-string">"dhcp-option DNS {{ core_addr }}"</span>
-      user nobody
-      group nogroup
-      persist-key
-      persist-tun
-      cipher AES-256-GCM
-      auth SHA256
-      max-clients 20
-      ifconfig-pool-persist ipp.txt
-      status openvpn-status.log
-      verb 3
-      ca /usr/local/share/ca-certificates/{{ domain_name }}.crt
-      cert server.crt
-      key server.key
-      dh dh2048.pem
-      tls-auth ta.key 0
+      &lt;&lt;openvpn-front&gt;&gt;
     dest: /etc/openvpn/server.conf
     <span class="org-variable-name">mode: u</span>=r,g=r,o=
   notify: Restart OpenVPN.
@@ -3054,7 +2868,7 @@ Finally, Kamailio can be configured and started.
   become: yes
   copy:
     content: |
-      <span class="org-variable-name">listen</span>=udp:{{ front_private_addr }}:5060
+      &lt;&lt;kamailio&gt;&gt;
     dest: /etc/kamailio/kamailio-local.cfg
   notify: Restart Kamailio.
 
@@ -3090,8 +2904,8 @@ Debian install and remote access to a privileged, administrator's
 account.  (For details, see <a href="#org8d60b7b">The Core Machine</a>.)
 </p>
 </div>
-<div id="outline-container-org27e3dcb" class="outline-3">
-<h3 id="org27e3dcb"><span class="section-number-3">8.1.</span> Include Particulars</h3>
+<div id="outline-container-orgb954e91" class="outline-3">
+<h3 id="orgb954e91"><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
@@ -3113,8 +2927,8 @@ particulars and membership roll.
 </div>
 </div>
 </div>
-<div id="outline-container-org410e0b9" class="outline-3">
-<h3 id="org410e0b9"><span class="section-number-3">8.2.</span> Configure Hostname</h3>
+<div id="outline-container-org64f83db" class="outline-3">
+<h3 id="org64f83db"><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
@@ -3147,8 +2961,8 @@ proper email delivery.
 </div>
 </div>
 </div>
-<div id="outline-container-org2ba83cb" class="outline-3">
-<h3 id="org2ba83cb"><span class="section-number-3">8.3.</span> Configure Systemd Resolved</h3>
+<div id="outline-container-org50a4e06" class="outline-3">
+<h3 id="org50a4e06"><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
@@ -3373,40 +3187,7 @@ The following tasks install and configure BIND9 on Core.
   become: yes
   copy:
     content: |
-      <span class="org-type">acl </span><span class="org-string"><span class="org-type">"trusted"</span></span> {
-          {{ private_net_cidr }};
-          {{ public_vpn_net_cidr }};
-          {{ campus_vpn_net_cidr }};
-          {{ gate_wifi_net_cidr }};
-          localhost;
-      };
-
-      <span class="org-type">options</span> {
-        directory <span class="org-string">"/var/cache/bind"</span>;
-
-        <span class="org-type">forwarders</span> {
-                8.8.4.4;
-                8.8.8.8;
-        };
-
-        allow-query { any; };
-        allow-recursion { trusted; };
-        allow-query-cache { trusted; };
-
-        <span class="org-variable-name">//</span>============================================================
-        // If BIND logs error messages about the root key being
-        // expired, you will need to update your keys.
-        // See https://www.isc.org/bind-keys
-        <span class="org-variable-name">//</span>============================================================
-        //dnssec-validation auto;
-        // If Secure DNS is too much of a headache...
-        dnssec-enable no;
-        dnssec-validation no;
-
-        auth-nxdomain no;    <span class="org-comment-delimiter"># </span><span class="org-comment">conform to RFC1035</span>
-        //listen-on-v6 { any; };
-        listen-on { {{ core_addr }}; };
-      };
+      &lt;&lt;bind-options&gt;&gt;
     dest: /etc/bind/named.conf.options
   notify: Reload BIND9.
 
@@ -3414,30 +3195,7 @@ The following tasks install and configure BIND9 on Core.
   become: yes
   copy:
     content: |
-      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;
-        file <span class="org-string">"/etc/bind/db.domain"</span>;
-      };
-
-      <span class="org-type">zone </span><span class="org-string"><span class="org-type">"{</span></span><span class="org-string">{ private_net_cidr | ipaddr('revdns')</span>
-<span class="org-string">               </span><span class="org-string"><span class="org-type">| regex_replace('^0\.','') }}"</span></span> {
-        type master;
-        file <span class="org-string">"/etc/bind/db.private"</span>;
-      };
-
-      <span class="org-type">zone </span><span class="org-string"><span class="org-type">"{</span></span><span class="org-string">{ public_vpn_net_cidr | ipaddr('revdns')</span>
-<span class="org-string">               </span><span class="org-string"><span class="org-type">| regex_replace('^0\.','') }}"</span></span> {
-        type master;
-        file <span class="org-string">"/etc/bind/db.public_vpn"</span>;
-      };
-
-      <span class="org-type">zone </span><span class="org-string"><span class="org-type">"{</span></span><span class="org-string">{ campus_vpn_net_cidr | ipaddr('revdns')</span>
-<span class="org-string">               </span><span class="org-string"><span class="org-type">| regex_replace('^0\.','') }}"</span></span> {
-        type master;
-        file <span class="org-string">"/etc/bind/db.campus_vpn"</span>;
-      };
+      &lt;&lt;bind-local&gt;&gt;
     dest: /etc/bind/named.conf.local
   notify: Reload BIND9.
 
@@ -3627,8 +3385,8 @@ craps up <q>/var/log/</q> and the Systemd journal.
 </div>
 </div>
 </div>
-<div id="outline-container-org31f8f68" class="outline-3">
-<h3 id="org31f8f68"><span class="section-number-3">8.7.</span> Add Administrator to System Groups</h3>
+<div id="outline-container-org1d7bca1" class="outline-3">
+<h3 id="org1d7bca1"><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
@@ -3648,8 +3406,8 @@ these groups speeds up debugging.
 </div>
 </div>
 </div>
-<div id="outline-container-org4690ba9" class="outline-3">
-<h3 id="org4690ba9"><span class="section-number-3">8.8.</span> Configure Monkey</h3>
+<div id="outline-container-org4dc1eb8" class="outline-3">
+<h3 id="org4dc1eb8"><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
@@ -3716,8 +3474,8 @@ described in <a href="#org1ac6235">*Configure Apache2</a>).
 </div>
 </div>
 </div>
-<div id="outline-container-org51e48da" class="outline-3">
-<h3 id="org51e48da"><span class="section-number-3">8.9.</span> Install Unattended Upgrades</h3>
+<div id="outline-container-org3075413" class="outline-3">
+<h3 id="org3075413"><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.
@@ -3749,8 +3507,8 @@ with Nextcloud on the command line.
 </div>
 </div>
 </div>
-<div id="outline-container-org3914dca" class="outline-3">
-<h3 id="org3914dca"><span class="section-number-3">8.11.</span> Configure User Accounts</h3>
+<div id="outline-container-org328bd8d" class="outline-3">
+<h3 id="org328bd8d"><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
@@ -3792,8 +3550,8 @@ describes the <code>members</code> and <code>usernames</code> variables.
 </div>
 </div>
 </div>
-<div id="outline-container-org1d9e0cd" class="outline-3">
-<h3 id="org1d9e0cd"><span class="section-number-3">8.12.</span> Install Server Certificate</h3>
+<div id="outline-container-org4b51fec" class="outline-3">
+<h3 id="org4b51fec"><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
@@ -3908,24 +3666,14 @@ The complete list of Core's Postfix settings for
 </p>
 
 <div class="org-src-container">
-<code>postfix-core</code><pre class="src src-conf" id="org4ccefef">- p: smtpd_relay_restrictions
-  v: permit_mynetworks reject_unauth_destination
+<code>postfix-core</code><pre class="src src-conf" id="org4ccefef">&lt;&lt;postfix-relaying&gt;&gt;
 - { p: smtpd_tls_security_level, v: none }
 - { p: smtp_tls_security_level, v: none }
-- { p: message_size_limit, v: 104857600 }
-- { p: delay_warning_time, v: 1h }
-- { p: maximal_queue_lifetime, v: 4h }
-- { p: bounce_queue_lifetime, v: 4h }
-- { p: home_mailbox, v: Maildir/ }
-- p: mynetworks
-  v: &gt;-
-     {{ private_net_cidr }}
-     {{ public_vpn_net_cidr }}
-     {{ campus_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
-- { p: relayhost, v: <span class="org-string">"[{{ front_private_addr }}]"</span> }
+&lt;&lt;postfix-message-size&gt;&gt;
+&lt;&lt;postfix-queue-times&gt;&gt;
+&lt;&lt;postfix-maildir&gt;&gt;
+&lt;&lt;postfix-core-networks&gt;&gt;
+&lt;&lt;postfix-core-relayhost&gt;&gt;
 - { p: inet_interfaces, v: <span class="org-string">"127.0.0.1 {{ core_addr }}"</span> }
 </pre>
 </div>
@@ -3950,25 +3698,7 @@ enable the service.  Whenever <q>/etc/postfix/transport</q> is changed, the
     regexp: <span class="org-string">"^ *{{ item.p }} *="</span>
     line: <span class="org-string">"{{ item.p }} = {{ item.v }}"</span>
   loop:
-  - p: smtpd_relay_restrictions
-    v: permit_mynetworks reject_unauth_destination
-  - { p: smtpd_tls_security_level, v: none }
-  - { p: smtp_tls_security_level, v: none }
-  - { p: message_size_limit, v: 104857600 }
-  - { p: delay_warning_time, v: 1h }
-  - { p: maximal_queue_lifetime, v: 4h }
-  - { p: bounce_queue_lifetime, v: 4h }
-  - { p: home_mailbox, v: Maildir/ }
-  - p: mynetworks
-    v: &gt;-
-       {{ private_net_cidr }}
-       {{ public_vpn_net_cidr }}
-       {{ campus_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
-  - { p: relayhost, v: <span class="org-string">"[{{ front_private_addr }}]"</span> }
-  - { p: inet_interfaces, v: <span class="org-string">"127.0.0.1 {{ core_addr }}"</span> }
+  &lt;&lt;postfix-core&gt;&gt;
   - { p: transport_maps, v: <span class="org-string">"hash:/etc/postfix/transport"</span> }
   notify: Restart Postfix.
 
@@ -3976,8 +3706,7 @@ enable the service.  Whenever <q>/etc/postfix/transport</q> is changed, the
   become: yes
   copy:
     content: |
-      .{{ domain_name }}        local:$myhostname
-      .{{ domain_priv }}        local:$myhostname
+      &lt;&lt;postfix-transport&gt;&gt;
     dest: /etc/postfix/transport
   notify: Postmap transport.
 
@@ -4046,8 +3775,8 @@ installed by more specialized roles.
 </div>
 </div>
 </div>
-<div id="outline-container-org1e54e7f" class="outline-3">
-<h3 id="org1e54e7f"><span class="section-number-3">8.16.</span> Configure Dovecot IMAPd</h3>
+<div id="outline-container-org26190b7" class="outline-3">
+<h3 id="org26190b7"><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
@@ -4084,11 +3813,10 @@ and enables it to start at every reboot.
   become: yes
   copy:
     content: |
-      <span class="org-variable-name">protocols</span> = imap
-      <span class="org-variable-name">ssl</span> = required
+      &lt;&lt;dovecot-tls&gt;&gt;
       <span class="org-variable-name">ssl_cert</span> = &lt;/etc/server.crt
       <span class="org-variable-name">ssl_key</span> = &lt;/etc/server.key
-      <span class="org-variable-name">mail_location</span> = maildir:~/Maildir
+      &lt;&lt;dovecot-maildir&gt;&gt;
     dest: /etc/dovecot/local.conf
   notify: Restart Dovecot.
 
@@ -4152,8 +3880,8 @@ The Systemd service description.
 <code>fetchmail-service</code><pre class="src src-conf" id="org712bd17">[<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">Requires</span>=sys-devices-virtual-net-ovpn.device
-<span class="org-variable-name">After</span>=sys-devices-virtual-net-ovpn.device
+<span class="org-variable-name">After</span>=openvpn@front.service
+<span class="org-variable-name">Wants</span>=sys-devices-virtual-net-ovpn.device
 
 [<span class="org-type">Service</span>]
 <span class="org-variable-name">User</span>={{ item }}
@@ -4186,17 +3914,7 @@ provided the Core service.
   become: yes
   copy:
     content: |
-      <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
-      set no syslog
-      <span class="org-comment-delimiter">#</span><span class="org-comment">set logfile /home/{{ item }}/.fetchmail.log</span>
-
-      poll {{ front_private_addr }} protocol imap timeout 15
-          username {{ item }}
-          password <span class="org-string">"{{ members[item].password_fetchmail }}"</span> fetchall
-          ssl sslproto tls1.2+ sslcertck sslcommonname {{ domain_name }}
+      &lt;&lt;fetchmail-config&gt;&gt;
     dest: /home/{{ item }}/.fetchmailrc
     owner: <span class="org-string">"{{ item }}"</span>
     group: <span class="org-string">"{{ item }}"</span>
@@ -4211,21 +3929,7 @@ provided the Core service.
   become: yes
   copy:
     content: |
-      [<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">Requires</span>=sys-devices-virtual-net-ovpn.device
-      <span class="org-variable-name">After</span>=sys-devices-virtual-net-ovpn.device
-
-      [<span class="org-type">Service</span>]
-      <span class="org-variable-name">User</span>={{ item }}
-      <span class="org-variable-name">ExecStart</span>=/usr/bin/fetchmail --idle
-      <span class="org-variable-name">Restart</span>=always
-      <span class="org-variable-name">RestartSec</span>=1m
-      <span class="org-variable-name">NoNewPrivileges</span>=true
-
-      [<span class="org-type">Install</span>]
-      <span class="org-variable-name">WantedBy</span>=default.target
+      &lt;&lt;fetchmail-service&gt;&gt;
     dest: /etc/systemd/system/fetchmail-{{ item }}.service
   loop: <span class="org-string">"{{ usernames }}"</span>
   when:
@@ -4392,11 +4096,7 @@ redirect, the encryption ciphers and certificates.
                 AllowOverride None
         &lt;/Directory&gt;
 
-        UserDir Public/HTML
-        &lt;Directory /home/*/Public/HTML/&gt;
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
+        &lt;&lt;apache-userdir-core&gt;&gt;
 
         ErrorLog ${APACHE_LOG_DIR}/live-error.log
         CustomLog ${APACHE_LOG_DIR}/live-access.log combined
@@ -4423,11 +4123,7 @@ familiar.
                 AllowOverride None
         &lt;/Directory&gt;
 
-        UserDir Public/HTML
-        &lt;Directory /home/*/Public/HTML/&gt;
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
+        &lt;&lt;apache-userdir-core&gt;&gt;
 
         ErrorLog ${APACHE_LOG_DIR}/test-error.log
         CustomLog ${APACHE_LOG_DIR}/test-access.log combined
@@ -4458,11 +4154,7 @@ trained staffers, monitored by a revision control system, etc.
                 AllowOverride None
         &lt;/Directory&gt;
 
-        UserDir Public/HTML
-        &lt;Directory /home/*/Public/HTML/&gt;
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
+        &lt;&lt;apache-userdir-core&gt;&gt;
 
         ErrorLog ${APACHE_LOG_DIR}/campus-error.log
         CustomLog ${APACHE_LOG_DIR}/campus-access.log combined
@@ -4525,28 +4217,7 @@ The <code>a2ensite</code> command enables them.
   become: yes
   copy:
     content: |
-      &lt;VirtualHost *:80&gt;
-        ServerName live
-        ServerAlias live.{{ domain_priv }}
-        ServerAdmin webmaster@core.{{ domain_priv }}
-
-        DocumentRoot /WWW/live
-        &lt;Directory /WWW/live/&gt;
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
-
-        UserDir Public/HTML
-        &lt;Directory /home/*/Public/HTML/&gt;
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
-
-        ErrorLog ${APACHE_LOG_DIR}/live-error.log
-        CustomLog ${APACHE_LOG_DIR}/live-access.log combined
-
-        IncludeOptional /etc/apache2/sites-available/live-vhost.conf
-      &lt;/VirtualHost&gt;
+      &lt;&lt;apache-live&gt;&gt;
     dest: /etc/apache2/sites-available/live.conf
     <span class="org-variable-name">mode: u</span>=rw,g=r,o=r
   notify: Restart Apache2.
@@ -4555,28 +4226,7 @@ The <code>a2ensite</code> command enables them.
   become: yes
   copy:
     content: |
-      &lt;VirtualHost *:80&gt;
-        ServerName test
-        ServerAlias test.{{ domain_priv }}
-        ServerAdmin webmaster@core.{{ domain_priv }}
-
-        DocumentRoot /WWW/test
-        &lt;Directory /WWW/test/&gt;
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
-
-        UserDir Public/HTML
-        &lt;Directory /home/*/Public/HTML/&gt;
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
-
-        ErrorLog ${APACHE_LOG_DIR}/test-error.log
-        CustomLog ${APACHE_LOG_DIR}/test-access.log combined
-
-        IncludeOptional /etc/apache2/sites-available/test-vhost.conf
-      &lt;/VirtualHost&gt;
+      &lt;&lt;apache-test&gt;&gt;
     dest: /etc/apache2/sites-available/test.conf
     <span class="org-variable-name">mode: u</span>=rw,g=r,o=r
   notify: Restart Apache2.
@@ -4585,30 +4235,7 @@ The <code>a2ensite</code> command enables them.
   become: yes
   copy:
     content: |
-      &lt;VirtualHost *:80&gt;
-        ServerName www
-        ServerAlias www.{{ domain_priv }}
-        ServerAdmin webmaster@core.{{ domain_priv }}
-
-        DocumentRoot /WWW/campus
-        &lt;Directory /WWW/campus/&gt;
-                Options Indexes FollowSymLinks MultiViews ExecCGI
-                AddHandler cgi-script .cgi
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
-
-        UserDir Public/HTML
-        &lt;Directory /home/*/Public/HTML/&gt;
-                Require all granted
-                AllowOverride None
-        &lt;/Directory&gt;
-
-        ErrorLog ${APACHE_LOG_DIR}/campus-error.log
-        CustomLog ${APACHE_LOG_DIR}/campus-access.log combined
-
-        IncludeOptional /etc/apache2/sites-available/www-vhost.conf
-      &lt;/VirtualHost&gt;
+      &lt;&lt;apache-campus&gt;&gt;
     dest: /etc/apache2/sites-available/www.conf
     <span class="org-variable-name">mode: u</span>=rw,g=r,o=r
   notify: Restart Apache2.
@@ -4715,12 +4342,8 @@ dev-type tun
 dev ovpn
 remote {{ front_addr }}
 nobind
-user nobody
-group nogroup
-persist-key
-persist-tun
-cipher AES-256-GCM
-auth SHA256
+&lt;&lt;openvpn-drop-priv&gt;&gt;
+&lt;&lt;openvpn-crypt&gt;&gt;
 remote-cert-tls server
 verify-x509-name {{ domain_name }} name
 verb 3
@@ -4772,24 +4395,7 @@ for Core.
   become: yes
   copy:
     content: |
-      client
-      dev-type tun
-      dev ovpn
-      remote {{ front_addr }}
-      nobind
-      user nobody
-      group nogroup
-      persist-key
-      persist-tun
-      cipher AES-256-GCM
-      auth SHA256
-      remote-cert-tls server
-      verify-x509-name {{ domain_name }} name
-      verb 3
-      ca /usr/local/share/ca-certificates/{{ domain_name }}.crt
-      cert client.crt
-      key client.key
-      tls-auth ta.key 1
+      &lt;&lt;openvpn-core&gt;&gt;
     dest: /etc/openvpn/front.conf
     <span class="org-variable-name">mode: u</span>=r,g=r,o=
   notify: Restart OpenVPN.
@@ -5953,8 +5559,8 @@ applied first, by which Gate gets a campus machine's DNS and Postfix
 configurations, etc.
 </p>
 </div>
-<div id="outline-container-org50cbfd6" class="outline-3">
-<h3 id="org50cbfd6"><span class="section-number-3">9.1.</span> Include Particulars</h3>
+<div id="outline-container-orgf2f2ea0" class="outline-3">
+<h3 id="orgf2f2ea0"><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.
@@ -6206,17 +5812,12 @@ sudo ufw enable
     block: |
       *nat
       :POSTROUTING ACCEPT [0:0]
-      -A POSTROUTING -s {{   private_net_cidr }} -o isp -j MASQUERADE
-      -A POSTROUTING -s {{ gate_wifi_net_cidr }} -o isp -j MASQUERADE
+      &lt;&lt;ufw-nat&gt;&gt;
       COMMIT
 
       *filter
-      -A FORWARD -i lan  -o isp  -j ACCEPT
-      -A FORWARD -i wifi -o isp  -j ACCEPT
-      -A FORWARD -i isp  -o lan  {{ ACCEPT_RELATED }}
-      -A FORWARD -i isp  -o wifi {{ ACCEPT_RELATED }}
-      -A FORWARD -i lan  -o ovpn -j ACCEPT
-      -A FORWARD -i ovpn -o lan  -j ACCEPT
+      &lt;&lt;ufw-forward-nat&gt;&gt;
+      &lt;&lt;ufw-forward-private&gt;&gt;
       COMMIT
     insertafter: EOF
 </pre>
@@ -6328,8 +5929,8 @@ the daemon listens <i>only</i> on the Gate-WiFi network interface.
 </div>
 </div>
 </div>
-<div id="outline-container-org4e379f9" class="outline-3">
-<h3 id="org4e379f9"><span class="section-number-3">9.6.</span> Install Server Certificate</h3>
+<div id="outline-container-org2ab49c8" class="outline-3">
+<h3 id="org2ab49c8"><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)
@@ -6356,8 +5957,8 @@ and Front) do.
 </div>
 </div>
 </div>
-<div id="outline-container-orgf00aa15" class="outline-3">
-<h3 id="orgf00aa15"><span class="section-number-3">9.7.</span> Configure OpenVPN</h3>
+<div id="outline-container-orgf920b5f" class="outline-3">
+<h3 id="orgf920b5f"><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
@@ -6382,25 +5983,14 @@ discussed in <a href="#orgc2baf19">The VPN Services</a>.
 <div class="org-src-container">
 <code>openvpn-gate</code><pre class="src src-conf" id="org95cfc89">server {{ campus_vpn_net_and_mask }}
 client-config-dir /etc/openvpn/ccd
-push <span class="org-string">"route {{ private_net_and_mask }}"</span>
-push <span class="org-string">"route {{ public_vpn_net_and_mask }}"</span>
-dev-type tun
-dev ovpn
-topology subnet
-client-to-client
-keepalive 10 120
-push <span class="org-string">"dhcp-option DOMAIN {{ domain_priv }}"</span>
-push <span class="org-string">"dhcp-option DNS {{ core_addr }}"</span>
-user nobody
-group nogroup
-persist-key
-persist-tun
-cipher AES-256-GCM
-auth SHA256
-max-clients 20
-ifconfig-pool-persist ipp.txt
-status openvpn-status.log
-verb 3
+&lt;&lt;openvpn-gate-routes&gt;&gt;
+&lt;&lt;openvpn-dev-mode&gt;&gt;
+&lt;&lt;openvpn-keepalive&gt;&gt;
+&lt;&lt;openvpn-dns&gt;&gt;
+&lt;&lt;openvpn-drop-priv&gt;&gt;
+&lt;&lt;openvpn-crypt&gt;&gt;
+&lt;&lt;openvpn-max&gt;&gt;
+&lt;&lt;openvpn-debug&gt;&gt;
 ca /usr/local/share/ca-certificates/{{ domain_name }}.crt
 cert /etc/server.crt
 key /etc/server.key
@@ -6458,32 +6048,7 @@ configure the OpenVPN server on Gate.
   become: yes
   copy:
     content: |
-      server {{ campus_vpn_net_and_mask }}
-      client-config-dir /etc/openvpn/ccd
-      push <span class="org-string">"route {{ private_net_and_mask }}"</span>
-      push <span class="org-string">"route {{ public_vpn_net_and_mask }}"</span>
-      dev-type tun
-      dev ovpn
-      topology subnet
-      client-to-client
-      keepalive 10 120
-      push <span class="org-string">"dhcp-option DOMAIN {{ domain_priv }}"</span>
-      push <span class="org-string">"dhcp-option DNS {{ core_addr }}"</span>
-      user nobody
-      group nogroup
-      persist-key
-      persist-tun
-      cipher AES-256-GCM
-      auth SHA256
-      max-clients 20
-      ifconfig-pool-persist ipp.txt
-      status openvpn-status.log
-      verb 3
-      ca /usr/local/share/ca-certificates/{{ domain_name }}.crt
-      cert /etc/server.crt
-      key /etc/server.key
-      dh dh2048.pem
-      tls-auth ta.key 0
+      &lt;&lt;openvpn-gate&gt;&gt;
     dest: /etc/openvpn/server.conf
     <span class="org-variable-name">mode: u</span>=r,g=r,o=
   notify: Restart OpenVPN.
@@ -6520,8 +6085,8 @@ Wireless campus devices can get a key to the campus VPN from the
 configured manually.
 </p>
 </div>
-<div id="outline-container-org8108a78" class="outline-3">
-<h3 id="org8108a78"><span class="section-number-3">10.1.</span> Include Particulars</h3>
+<div id="outline-container-org4e59c64" class="outline-3">
+<h3 id="org4e59c64"><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.
@@ -6537,8 +6102,8 @@ The following should be familiar boilerplate by now.
 </div>
 </div>
 </div>
-<div id="outline-container-org2e7e75f" class="outline-3">
-<h3 id="org2e7e75f"><span class="section-number-3">10.2.</span> Configure Hostname</h3>
+<div id="outline-container-org2ecf1fc" class="outline-3">
+<h3 id="org2ecf1fc"><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.
@@ -6565,8 +6130,8 @@ Clients should be using the expected host name.
 </div>
 </div>
 </div>
-<div id="outline-container-org89c7cf2" class="outline-3">
-<h3 id="org89c7cf2"><span class="section-number-3">10.3.</span> Configure Systemd Resolved</h3>
+<div id="outline-container-orge61e556" class="outline-3">
+<h3 id="orge61e556"><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>),
@@ -6637,8 +6202,8 @@ and file timestamps.
 </div>
 </div>
 </div>
-<div id="outline-container-org9767066" class="outline-3">
-<h3 id="org9767066"><span class="section-number-3">10.5.</span> Add Administrator to System Groups</h3>
+<div id="outline-container-org0365651" class="outline-3">
+<h3 id="org0365651"><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
@@ -6658,8 +6223,8 @@ these groups speeds up debugging.
 </div>
 </div>
 </div>
-<div id="outline-container-org1c243d8" class="outline-3">
-<h3 id="org1c243d8"><span class="section-number-3">10.6.</span> Install Unattended Upgrades</h3>
+<div id="outline-container-orged061bf" class="outline-3">
+<h3 id="orged061bf"><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.
@@ -6704,13 +6269,10 @@ tasks below.
     regexp: <span class="org-string">"^ *{{ item.p }} *="</span>
     line: <span class="org-string">"{{ item.p }} = {{ item.v }}"</span>
   loop:
-  - p: smtpd_relay_restrictions
-    v: permit_mynetworks reject_unauth_destination
-  - { p: message_size_limit, v: 104857600 }
-  - { p: delay_warning_time, v: 1h }
-  - { p: maximal_queue_lifetime, v: 4h }
-  - { p: bounce_queue_lifetime, v: 4h }
-  - { p: home_mailbox, v: Maildir/ }
+  &lt;&lt;postfix-relaying&gt;&gt;
+  &lt;&lt;postfix-message-size&gt;&gt;
+  &lt;&lt;postfix-queue-times&gt;&gt;
+  &lt;&lt;postfix-maildir&gt;&gt;
   <span class="org-type">-</span> { p: myhostname,
       v: <span class="org-string">"{{ inventory_hostname }}.{{ domain_priv }}"</span> }
   <span class="org-type">-</span> { p: mydestination,
@@ -8172,9 +7734,7 @@ up-restart
   <span class="org-type">my</span> $<span class="org-variable-name">CRT</span> = read_file <span class="org-string">"Secret/CA/pki/issued/$name.crt"</span>;
   <span class="org-type">my</span> $<span class="org-variable-name">KEY</span> = read_file <span class="org-string">"Secret/CA/pki/private/$name.key"</span>;
   <span class="org-type">my</span> $<span class="org-variable-name">UP</span> = $<span class="org-variable-name">type</span> eq <span class="org-string">"android"</span> ? <span class="org-string">""</span> : <span class="org-string">"</span>
-<span class="org-string">script-security 2</span>
-<span class="org-string">up /etc/openvpn/update-systemd-resolved</span>
-<span class="org-string">up-restart"</span>;
+<span class="org-string">&lt;&lt;openvpn-up&gt;&gt;"</span>;
 
   <span class="org-keyword">if</span> ($<span class="org-variable-name">type</span> ne <span class="org-string">"campus"</span>) {
     <span class="org-type">my</span> $<span class="org-variable-name">TA</span> = read_file <span class="org-string">"Secret/front-ta.key"</span>;
@@ -8199,14 +7759,10 @@ up-restart
 <span class="org-string">dev $DEV</span>
 <span class="org-string">remote $ADDR</span>
 <span class="org-string">nobind</span>
-<span class="org-string">user nobody</span>
-<span class="org-string">group nogroup</span>
-<span class="org-string">persist-key</span>
-<span class="org-string">persist-tun</span>
+<span class="org-string">&lt;&lt;openvpn-drop-priv&gt;&gt;</span>
 <span class="org-string">remote-cert-tls server</span>
 <span class="org-string">verify-x509-name $NAME name</span>
-<span class="org-string">cipher AES-256-GCM</span>
-<span class="org-string">auth SHA256$UP</span>
+<span class="org-string">&lt;&lt;openvpn-crypt&gt;&gt;$UP</span>
 <span class="org-string">verb 3</span>
 <span class="org-string">key-direction 1</span>
 <span class="org-string">&lt;ca&gt;\n$CA&lt;/ca&gt;</span>
@@ -9608,7 +9164,7 @@ routes on Front and Gate, making the simulation less&#x2026; similar.
 </div></div>
 <div id="postamble" class="status">
 <p class="author">Author: Matt Birkholz</p>
-<p class="date">Created: 2024-02-26 Mon 21:58</p>
+<p class="date">Created: 2024-03-09 Sat 10:34</p>
 <p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
 </div>
 </body>
index da9e560a54e5bb91d195945092e4755a46e41644..f0756e848fe36e9723f227890bb8b7f4e3817333 100644 (file)
@@ -3893,7 +3893,7 @@ small institute substitutes a slightly modified version,
 ~inst_sensors~, that reports core CPU temperatures.
 
 #+CAPTION: [[file:roles_t/core/files/inst_sensors][=roles_t/core/files/inst_sensors=]]
-#+BEGIN_SRC sh :tangle roles_t/core/files/inst_sensors
+#+BEGIN_SRC sh :tangle roles_t/core/files/inst_sensors :mkdirp yes
 #!/bin/sh
 
 PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"