"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>
members off campus.
</p>
-<pre class="example" id="org08ed86c">
+<pre class="example" id="org908d63b">
=
_|||_
=-The-Institute-=
</pre>
</div>
-<div class="TEXT" id="org6d1f744">
+<div class="TEXT" id="orgb05406e">
<p>
=> 10.62.17.0/24
</p>
campground Wi-Fi access point, etc.</li>
</ol>
-<pre class="example" id="org9575410">
+<pre class="example" id="org9215090">
=============== | ==================================================
| Premises
(Campus ISP)
following topology.
</p>
-<pre class="example" id="org1a67bf1">
+<pre class="example" id="org451080a">
=============== | ==================================================
| Premises
(House ISP)
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
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
</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
</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
</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
</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.
</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
</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
<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: >-
- {{ 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: >-
- 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
+<<postfix-front-networks>>
+<<postfix-front-restrictions>>
+<<postfix-relaying>>
+<<postfix-message-size>>
+<<postfix-queue-times>>
+<<postfix-maildir>>
+<<postfix-header-checks>>
</pre>
</div>
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: >-
- {{ 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: >-
- 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
+ <<postfix-front>>
notify: Restart Postfix.
- name: Install Postfix header_checks.
become: yes
copy:
content: |
- /^Received:/ IGNORE
- /^User-Agent:/ IGNORE
+ <<postfix-header-checks-content>>
dest: /etc/postfix/header_checks.cf
notify: Postmap header checks.
</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
become: yes
copy:
content: |
- <span class="org-variable-name">protocols</span> = imap
- <span class="org-variable-name">ssl</span> = required
+ <<dovecot-tls>>
<span class="org-variable-name">ssl_cert</span> = </etc/server.crt
<span class="org-variable-name">ssl_key</span> = </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
+ <<dovecot-ports>>
+ <<dovecot-maildir>>
dest: /etc/dovecot/local.conf
notify: Restart Dovecot.
<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">
</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
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">
AllowOverride None
</Directory>
-UserDir /home/www-users
-<Directory /home/www-users/>
- Require all granted
- AllowOverride None
-</Directory>
+<<apache-userdir-front>>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
-<VirtualHost *:80>
- Redirect permanent / https://{{ domain_name }}/
-</VirtualHost>
+<<apache-redirect-front>>
<VirtualHost *:443>
SSLEngine on
/etc/apache2/sites-available/{{ domain_name }}-vhost.conf
</VirtualHost>
-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>) }}
+<<apache-ciphers>>
</pre>
</div>
become: yes
copy:
content: |
- ServerName {{ domain_name }}
- ServerAdmin webmaster@{{ domain_name }}
-
- DocumentRoot /home/www
- <Directory /home/www/>
- Require all granted
- AllowOverride None
- </Directory>
-
- UserDir /home/www-users
- <Directory /home/www-users/>
- Require all granted
- AllowOverride None
- </Directory>
-
- ErrorLog ${APACHE_LOG_DIR}/error.log
- CustomLog ${APACHE_LOG_DIR}/access.log combined
-
- <VirtualHost *:80>
- Redirect permanent / https://{{ domain_name }}/
- </VirtualHost>
-
- <VirtualHost *:443>
- SSLEngine on
- SSLCertificateFile /etc/server.crt
- SSLCertificateKeyFile /etc/server.key
- IncludeOptional \
- /etc/apache2/sites-available/{{ domain_name }}-vhost.conf
- </VirtualHost>
-
- 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>) }}
+ <<apache-front>>
dest: /etc/apache2/sites-available/{{ domain_name }}.conf
notify: Restart Apache2.
</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
<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
+<<openvpn-front-routes>>
+<<openvpn-dev-mode>>
+<<openvpn-keepalive>>
+<<openvpn-dns>>
+<<openvpn-drop-priv>>
+<<openvpn-crypt>>
+<<openvpn-max>>
+<<openvpn-debug>>
ca /usr/local/share/ca-certificates/{{ domain_name }}.crt
cert server.crt
key server.key
become: yes
copy:
content: |
- iroute {{ private_net_and_mask }}
- iroute {{ campus_vpn_net_and_mask }}
+ <<openvpn-ccd-core>>
dest: /etc/openvpn/ccd/core
notify: Restart OpenVPN.
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
+ <<openvpn-front>>
dest: /etc/openvpn/server.conf
<span class="org-variable-name">mode: u</span>=r,g=r,o=
notify: Restart OpenVPN.
become: yes
copy:
content: |
- <span class="org-variable-name">listen</span>=udp:{{ front_private_addr }}:5060
+ <<kamailio>>
dest: /etc/kamailio/kamailio-local.cfg
notify: Restart Kamailio.
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
</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
</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
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 }}; };
- };
+ <<bind-options>>
dest: /etc/bind/named.conf.options
notify: Reload BIND9.
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>;
- };
+ <<bind-local>>
dest: /etc/bind/named.conf.local
notify: Reload BIND9.
</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
</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
</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.
</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
</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
</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"><<postfix-relaying>>
- { 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: >-
- {{ 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> }
+<<postfix-message-size>>
+<<postfix-queue-times>>
+<<postfix-maildir>>
+<<postfix-core-networks>>
+<<postfix-core-relayhost>>
- { p: inet_interfaces, v: <span class="org-string">"127.0.0.1 {{ core_addr }}"</span> }
</pre>
</div>
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: >-
- {{ 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> }
+ <<postfix-core>>
- { p: transport_maps, v: <span class="org-string">"hash:/etc/postfix/transport"</span> }
notify: Restart Postfix.
become: yes
copy:
content: |
- .{{ domain_name }} local:$myhostname
- .{{ domain_priv }} local:$myhostname
+ <<postfix-transport>>
dest: /etc/postfix/transport
notify: Postmap transport.
</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
become: yes
copy:
content: |
- <span class="org-variable-name">protocols</span> = imap
- <span class="org-variable-name">ssl</span> = required
+ <<dovecot-tls>>
<span class="org-variable-name">ssl_cert</span> = </etc/server.crt
<span class="org-variable-name">ssl_key</span> = </etc/server.key
- <span class="org-variable-name">mail_location</span> = maildir:~/Maildir
+ <<dovecot-maildir>>
dest: /etc/dovecot/local.conf
notify: Restart Dovecot.
<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 }}
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 }}
+ <<fetchmail-config>>
dest: /home/{{ item }}/.fetchmailrc
owner: <span class="org-string">"{{ item }}"</span>
group: <span class="org-string">"{{ item }}"</span>
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
+ <<fetchmail-service>>
dest: /etc/systemd/system/fetchmail-{{ item }}.service
loop: <span class="org-string">"{{ usernames }}"</span>
when:
AllowOverride None
</Directory>
- UserDir Public/HTML
- <Directory /home/*/Public/HTML/>
- Require all granted
- AllowOverride None
- </Directory>
+ <<apache-userdir-core>>
ErrorLog ${APACHE_LOG_DIR}/live-error.log
CustomLog ${APACHE_LOG_DIR}/live-access.log combined
AllowOverride None
</Directory>
- UserDir Public/HTML
- <Directory /home/*/Public/HTML/>
- Require all granted
- AllowOverride None
- </Directory>
+ <<apache-userdir-core>>
ErrorLog ${APACHE_LOG_DIR}/test-error.log
CustomLog ${APACHE_LOG_DIR}/test-access.log combined
AllowOverride None
</Directory>
- UserDir Public/HTML
- <Directory /home/*/Public/HTML/>
- Require all granted
- AllowOverride None
- </Directory>
+ <<apache-userdir-core>>
ErrorLog ${APACHE_LOG_DIR}/campus-error.log
CustomLog ${APACHE_LOG_DIR}/campus-access.log combined
become: yes
copy:
content: |
- <VirtualHost *:80>
- ServerName live
- ServerAlias live.{{ domain_priv }}
- ServerAdmin webmaster@core.{{ domain_priv }}
-
- DocumentRoot /WWW/live
- <Directory /WWW/live/>
- Require all granted
- AllowOverride None
- </Directory>
-
- UserDir Public/HTML
- <Directory /home/*/Public/HTML/>
- Require all granted
- AllowOverride None
- </Directory>
-
- ErrorLog ${APACHE_LOG_DIR}/live-error.log
- CustomLog ${APACHE_LOG_DIR}/live-access.log combined
-
- IncludeOptional /etc/apache2/sites-available/live-vhost.conf
- </VirtualHost>
+ <<apache-live>>
dest: /etc/apache2/sites-available/live.conf
<span class="org-variable-name">mode: u</span>=rw,g=r,o=r
notify: Restart Apache2.
become: yes
copy:
content: |
- <VirtualHost *:80>
- ServerName test
- ServerAlias test.{{ domain_priv }}
- ServerAdmin webmaster@core.{{ domain_priv }}
-
- DocumentRoot /WWW/test
- <Directory /WWW/test/>
- Require all granted
- AllowOverride None
- </Directory>
-
- UserDir Public/HTML
- <Directory /home/*/Public/HTML/>
- Require all granted
- AllowOverride None
- </Directory>
-
- ErrorLog ${APACHE_LOG_DIR}/test-error.log
- CustomLog ${APACHE_LOG_DIR}/test-access.log combined
-
- IncludeOptional /etc/apache2/sites-available/test-vhost.conf
- </VirtualHost>
+ <<apache-test>>
dest: /etc/apache2/sites-available/test.conf
<span class="org-variable-name">mode: u</span>=rw,g=r,o=r
notify: Restart Apache2.
become: yes
copy:
content: |
- <VirtualHost *:80>
- ServerName www
- ServerAlias www.{{ domain_priv }}
- ServerAdmin webmaster@core.{{ domain_priv }}
-
- DocumentRoot /WWW/campus
- <Directory /WWW/campus/>
- Options Indexes FollowSymLinks MultiViews ExecCGI
- AddHandler cgi-script .cgi
- Require all granted
- AllowOverride None
- </Directory>
-
- UserDir Public/HTML
- <Directory /home/*/Public/HTML/>
- Require all granted
- AllowOverride None
- </Directory>
-
- ErrorLog ${APACHE_LOG_DIR}/campus-error.log
- CustomLog ${APACHE_LOG_DIR}/campus-access.log combined
-
- IncludeOptional /etc/apache2/sites-available/www-vhost.conf
- </VirtualHost>
+ <<apache-campus>>
dest: /etc/apache2/sites-available/www.conf
<span class="org-variable-name">mode: u</span>=rw,g=r,o=r
notify: Restart Apache2.
dev ovpn
remote {{ front_addr }}
nobind
-user nobody
-group nogroup
-persist-key
-persist-tun
-cipher AES-256-GCM
-auth SHA256
+<<openvpn-drop-priv>>
+<<openvpn-crypt>>
remote-cert-tls server
verify-x509-name {{ domain_name }} name
verb 3
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
+ <<openvpn-core>>
dest: /etc/openvpn/front.conf
<span class="org-variable-name">mode: u</span>=r,g=r,o=
notify: Restart OpenVPN.
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.
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
+ <<ufw-nat>>
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
+ <<ufw-forward-nat>>
+ <<ufw-forward-private>>
COMMIT
insertafter: EOF
</pre>
</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)
</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
<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
+<<openvpn-gate-routes>>
+<<openvpn-dev-mode>>
+<<openvpn-keepalive>>
+<<openvpn-dns>>
+<<openvpn-drop-priv>>
+<<openvpn-crypt>>
+<<openvpn-max>>
+<<openvpn-debug>>
ca /usr/local/share/ca-certificates/{{ domain_name }}.crt
cert /etc/server.crt
key /etc/server.key
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
+ <<openvpn-gate>>
dest: /etc/openvpn/server.conf
<span class="org-variable-name">mode: u</span>=r,g=r,o=
notify: Restart OpenVPN.
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.
</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.
</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>),
</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
</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.
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/ }
+ <<postfix-relaying>>
+ <<postfix-message-size>>
+ <<postfix-queue-times>>
+ <<postfix-maildir>>
<span class="org-type">-</span> { p: myhostname,
v: <span class="org-string">"{{ inventory_hostname }}.{{ domain_priv }}"</span> }
<span class="org-type">-</span> { p: mydestination,
<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"><<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-type">my</span> $<span class="org-variable-name">TA</span> = read_file <span class="org-string">"Secret/front-ta.key"</span>;
<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"><<openvpn-drop-priv>></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"><<openvpn-crypt>>$UP</span>
<span class="org-string">verb 3</span>
<span class="org-string">key-direction 1</span>
<span class="org-string"><ca>\n$CA</ca></span>
</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>