Fixes for Testing as far as Nextcloud 31 installation.
authorMatt Birkholz <matt@birchwood-abbey.net>
Sun, 2 Nov 2025 22:04:55 +0000 (15:04 -0700)
committerMatt Birkholz <matt@birchwood-abbey.net>
Sun, 2 Nov 2025 22:04:55 +0000 (15:04 -0700)
- Ensure ~front~ gets ~front_addr~ by moving it to 192.168.15.3,
  hopefully outside the default DHCP pool.
- Expect ~front~ hostname to be FQDN.
- Don't warn about missing =~/Public/HTML= targets on ~front~.
- Include an alias for ~root~.  This was previously provided by the
  Postfix install.
- Un-truncate the Nextcloud DB password (to match Testing).
- Update Nextcloud installation instructions for version 31, including
  esp. the ~occ maintenance:install~ command and the link to the
  official "Installation from command line" instructions.
- Fix confused syntax in =templates/wild.network=.
- Add forward rules to ~ufw-before-forward~.  ~ufw-user-forward~ is
  reserved for rules generated per user requests.
- Use the Ansible ~ufw~ module to enable the firewall (without
  hanging).
- Fix initialization of ~members~ so that the first member is
  added to an empty hash and not undef.
- Quiet the ~./inst new~ command.
- Removed extra whitespace from many arguments to ~mysystem~ (sorry!).
- Changed name of simulated Internet from ~premises~ (as in the
  introductory diagram) to ~public~ (as in ISP and cloud).
- Statically assign IP addresses to both NICs on ~front~.
- Note need to restart ~gate~ after its first configuration.

README.org
inst
private/core-wg0.conf
private/members-empty.yml
private/test-front-prep
private/vars.yml
public/vars.yml
roles_t/core/tasks/main.yml
roles_t/front/tasks/main.yml
roles_t/gate/tasks/main.yml
roles_t/gate/templates/wild.network

index a19a55bc9e23eda179e1f296310225c5f125a6b1..8c9ab4c99376b704b787209213eb567084396712 100644 (file)
@@ -747,7 +747,7 @@ the institute's Internet domain name.
 
 #+CAPTION: [[file:public/vars.yml][=public/vars.yml=]]
 #+BEGIN_SRC conf :tangle public/vars.yml
-front_addr: 192.168.15.5
+front_addr: 192.168.15.3
 #+END_SRC
 
 The example address is a private network address because the example
@@ -1380,7 +1380,7 @@ delivery.
 - name: Update hostname.
   become: yes
   command: hostname -F /etc/hostname
-  when: domain_name != ansible_hostname
+  when: domain_name != ansible_fqdn
   tags: actualizer
 #+END_SRC
 
@@ -2076,6 +2076,7 @@ the users' =~/Public/HTML/= directories.
     src: /home/{{ item }}/Public/HTML
     state: link
     force: yes
+    follow: false
   loop: "{{ usernames }}"
   when: members[item].status == 'current'
   tags: accounts
@@ -2142,7 +2143,7 @@ PostUp = resolvectl dns %i 192.168.56.1
 PostUp = resolvectl domain %i small.private
 
 [Peer]
-EndPoint = 192.168.15.5:39608
+EndPoint = 192.168.15.3:39608
 PublicKey = S+6HaTnOwwhWgUGXjSBcPAvifKw+j8BDTRfq534gNW4=
 AllowedIPs = 10.177.87.1
 AllowedIPs = 192.168.56.0/24
@@ -3143,6 +3144,7 @@ installed by more specialized roles.
         admin:         root
         www-data:      root
         monkey:                root
+        root:          {{ ansible_user }}
     path: /etc/aliases
     marker: "# {mark} INSTITUTE MANAGED BLOCK"
   notify: New aliases.
@@ -3648,7 +3650,7 @@ PostUp = wg set %i private-key /etc/wireguard/private-key
 
 # Front
 [Peer]
-EndPoint = 192.168.15.5:39608
+EndPoint = 192.168.15.3:39608
 PublicKey = S+6HaTnOwwhWgUGXjSBcPAvifKw+j8BDTRfq534gNW4=
 AllowedIPs = 10.177.87.1
 AllowedIPs = 10.177.87.0/24
@@ -4269,7 +4271,7 @@ the ~apg -n 1 -x 12 -m 12~ command.
 
 #+CAPTION: [[file:private/vars.yml][=private/vars.yml=]]
 #+BEGIN_SRC conf :tangle private/vars.yml
-nextcloud_dbpass:           ippAgmaygyob
+nextcloud_dbpass:           ippAgmaygyobwyt5
 #+END_SRC
 
 When the ~mysql_db~ Ansible module supports ~check_implicit_admin~,
@@ -4318,6 +4320,9 @@ grant all on nextcloud.*
 flush privileges;
 #+END_SRC
 
+# Similar SQL is used in [[* Restore Nextcloud]] and [[* Install Nextcloud]].
+# Those SQL snippets and the above should be kept in sync!
+
 Finally, a symbolic link positions =/Nextcloud/nextcloud/= at
 =/var/www/nextcloud/= as expected by the Apache2 configuration above.
 Nextcloud itself should always believe that =/var/www/nextcloud/= is
@@ -4439,7 +4444,7 @@ All of the files in =/Nextcloud/nextcloud/= must be owned by user
 make it so.
 
 #+BEGIN_SRC sh
-sudo chown -R www-data.www-data /Nextcloud/nextcloud/
+sudo chown -R www-data:www-data /Nextcloud/nextcloud/
 #+END_SRC
 
 The database is restored with the following commands, which assume the
@@ -4463,6 +4468,9 @@ cd nextcloud/
 sudo -u www-data php occ maintenance:data-fingerprint
 #+END_SRC
 
+# Similar SQL is used in Configure Nextcloud and Install Nextcloud.
+# Those SQL snippets and the above should be kept in sync!
+
 Finally the administrator surfs to ~http://core/nextcloud/~,
 authenticates, and addresses any warnings on the Administration >
 Overview web page.
@@ -4471,25 +4479,26 @@ Overview web page.
 
 Installing Nextcloud in the newly created =/Nextcloud/= starts with
 downloading and verifying a recent release tarball.  The following
-example command lines unpacked Nextcloud 23 in =nextcloud/= in
+example command lines unpacked Nextcloud 31 in =nextcloud/= in
 =/Nextcloud/= and set the ownerships and permissions of the new
 directories and files.
 
 #+BEGIN_SRC sh
 cd /Nextcloud/
-tar xzf ~/Downloads/nextcloud-23.0.0.tar.bz2
-sudo chown -R www-data.www-data nextcloud
+tar xjf ~/Downloads/nextcloud-31.0.2.tar.bz2
+sudo chown -R www-data:www-data nextcloud
 sudo find nextcloud -type d -exec chmod 750 {} \;
 sudo find nextcloud -type f -exec chmod 640 {} \;
 #+END_SRC
 
-According to the latest installation instructions in version 24's
-administration guide, after unpacking and setting file permissions,
-the following ~occ~ command takes care of everything.  This command
-currently expects Nextcloud's database and user to exist.  The
-following SQL commands create the database and user (entered at the
-SQL prompt of the ~sudo mysql~ command).  The shell command then runs
-~occ~.
+According to the latest installation instructions in the Admin Manual
+for version 31 (section "Installation and server configuration",
+subsection "Installing from command line", [[https://docs.nextcloud.com/server/stable/admin_manual/installation/command_line_installation.html][here]]), after unpacking and
+setting file permissions, the following ~occ~ command takes care of
+everything.  This command currently expects Nextcloud's database and
+user to exist.  The following SQL commands create the database and
+user (entered at the SQL prompt of the ~sudo mysql~ command).  The
+shell command then runs ~occ~.
 
 #+BEGIN_SRC sql
 create database nextcloud
@@ -4501,14 +4510,15 @@ grant all on nextcloud.*
 flush privileges;
 #+END_SRC
 
+# Similar SQL is used in [[* Configure Nextcloud]] and [[* Restore Nextcloud]].
+# Those SQL snippets and the above should be kept in sync!
+
 #+BEGIN_SRC sh
 cd /var/www/nextcloud/
-sudo -u www-data php occ maintenance:install \
-     --data-dir=/var/www/nextcloud/data \
-     --database=mysql --database-name=nextcloud \
-     --database-user=nextclouduser \
-     --database-pass=ippAgmaygyobwyt5 \
-     --admin-user=sysadm --admin-pass=PASSWORD
+sudo -u www-data php occ  maintenance:install \
+--database='mysql' --database-name='nextcloud' \
+--database-user='nextclouduser' --database-pass='ippAgmaygyobwyt5' \
+--admin-user='sysadm' --admin-pass='fubar'
 #+END_SRC
 
 The =nextcloud/config/config.php= is created by the above command, but
@@ -4866,7 +4876,7 @@ SMTP={{ core_addr }}
 
 [DHCPServerStaticLease]
 MACAddress={{ wild.MAC }}
-Address={{ wild.num |ansible.utils.ipaddr('address') }}
+Address={{ wild_net_cidr |ansible.utils.ipaddr(wild.num) }}
 {% endfor %}
 #+END_SRC
 
@@ -4961,14 +4971,10 @@ connection tracking).
 #+NAME: ufw-forward-nat
 #+CAPTION: ~ufw-forward-nat~
 #+BEGIN_SRC conf
--A ufw-user-forward -i lan  -o isp -j ACCEPT
--A ufw-user-forward -i wild -o isp -j ACCEPT
+-A ufw-before-forward -i lan  -o isp -j ACCEPT
+-A ufw-before-forward -i wild -o isp -j ACCEPT
 #+END_SRC
 
-If "the standard ~iptables-restore~ syntax" as it is described in the
-~ufw-framework~ manual page, allows continuation lines, please let us
-know!
-
 Forwarding rules are also needed to route packets from the campus VPN
 (the ~wg0~ WireGuard™ tunnel device) to the institute's LAN and back.
 The public VPN on Front will also be included since its packets arrive
@@ -4978,9 +4984,9 @@ public and campus VPNs is also allowed.
 #+NAME: ufw-forward-private
 #+CAPTION: ~ufw-forward-private~
 #+BEGIN_SRC conf
--A ufw-user-forward -i lan  -o wg0 -j ACCEPT
--A ufw-user-forward -i wg0  -o lan -j ACCEPT
--A ufw-user-forward -i wg0  -o wg0 -j ACCEPT
+-A ufw-before-forward -i lan  -o wg0 -j ACCEPT
+-A ufw-before-forward -i wg0  -o lan -j ACCEPT
+-A ufw-before-forward -i wg0  -o wg0 -j ACCEPT
 #+END_SRC
 
 The third rule above may seem curious; it is.  It short circuits
@@ -4994,22 +5000,8 @@ the ~wild~ device to the ~lan~ device, just the ~wg0~ device.
 ** Configure UFW
 
 The following tasks install the Uncomplicated Firewall (UFW), set its
-policy in =/etc/default/ufw=, install the NAT rules in
-=/etc/ufw/before.rules=, and the Forward rules in
-=/etc/ufw/user.rules= (where the ~ufw-user-forward~ chain
-is... mentioned?).
-
-When Gate is configured by ~./abbey config gate~ as in the example
-bootstrap, enabling the firewall should not be a problem.  But when
-configuring a new gate with ~./abbey config new-gate~, enabling the
-firewall could break Ansible's current and future ssh sessions.  For
-this reason, Ansible /does not/ enable the firewall.
-
-The administrator must login and execute the following command after
-Gate is configured or new gate is "in position" (connected to old
-Gate's ~wild~ and ~isp~ networks).
-
-: sudo ufw enable
+policy in =/etc/default/ufw=, and install the institute's rules in
+=/etc/ufw/before.rules=.
 
 #+CAPTION: [[file:roles_t/gate/tasks/main.yml][=roles_t/gate/tasks/main.yml=]]
 #+BEGIN_SRC conf :tangle roles_t/gate/tasks/main.yml :noweb no-export
@@ -5032,7 +5024,7 @@ Gate's ~wild~ and ~isp~ networks).
   - { line: "DEFAULT_FORWARD_POLICY=\"DROP\"",
       regexp: "^DEFAULT_FORWARD_POLICY=" }
 
-- name: Configure UFW NAT rules.
+- name: Configure UFW rules.
   become: yes
   blockinfile:
     block: |
@@ -5040,21 +5032,18 @@ Gate's ~wild~ and ~isp~ networks).
       :POSTROUTING ACCEPT [0:0]
       <<ufw-nat>>
       COMMIT
-    dest: /etc/ufw/before.rules
-    insertafter: EOF
-    prepend_newline: yes
-
-- name: Configure UFW FORWARD rules.
-  become: yes
-  blockinfile:
-    block: |
       *filter
       <<ufw-forward-nat>>
       <<ufw-forward-private>>
       COMMIT
-    dest: /etc/ufw/user.rules
+    dest: /etc/ufw/before.rules
     insertafter: EOF
     prepend_newline: yes
+
+- name: Enable UFW.
+  become: yes
+  ufw: state=enabled
+  tags: actualizer
 #+END_SRC
 
 ** Configure Campus WireGuard™ Subnet
@@ -5905,28 +5894,28 @@ if (defined $ARGV[0] && $ARGV[0] eq "CA") {
 
   mysystem "mkdir --mode=700 Secret/root.gnupg";
   mysystem ("gpg --homedir Secret/root.gnupg",
-           " --batch --quick-generate-key --passphrase ''",
-           " root\@core.$pvt");
+           "--batch --quick-generate-key --passphrase ''",
+           "root\@core.$pvt");
   mysystem ("gpg --homedir Secret/root.gnupg",
-           " --export --armor --output Secret/root-pub.pem",
-           " root\@core.$pvt");
+           "--export --armor --output Secret/root-pub.pem",
+           "root\@core.$pvt");
   chmod 0440, "root-pub.pem";
   mysystem ("gpg --homedir Secret/root.gnupg",
-           " --export-secret-key --armor --output Secret/root-sec.pem",
-           " root\@core.$pvt");
+           "--export-secret-key --armor --output Secret/root-sec.pem",
+           "root\@core.$pvt");
   chmod 0400, "root-sec.pem";
 
   mysystem "mkdir Secret/ssh_admin";
   chmod 0700, "Secret/ssh_admin";
-  mysystem ("ssh-keygen -q -t rsa"
-           ." -C A\\ Small\\ Institute\\ Administrator",
-           " -N '' -f Secret/ssh_admin/id_rsa");
+  mysystem ("ssh-keygen -q -t rsa",
+           "-C A\\ Small\\ Institute\\ Administrator",
+           "-N '' -f Secret/ssh_admin/id_rsa");
 
   mysystem "mkdir Secret/ssh_monkey";
   chmod 0700, "Secret/ssh_monkey";
   mysystem "echo 'HashKnownHosts  no' >Secret/ssh_monkey/config";
   mysystem ("ssh-keygen -q -t rsa -C monkey\@core",
-           " -N '' -f Secret/ssh_monkey/id_rsa");
+           "-N '' -f Secret/ssh_monkey/id_rsa");
 
   mysystem "mkdir Secret/ssh_front";
   chmod 0700, "Secret/ssh_front";
@@ -6038,7 +6027,7 @@ is used instead.
 #+CAPTION: [[file:private/members-empty.yml][=private/members-empty.yml=]]
 #+BEGIN_SRC conf :tangle private/members-empty.yml :tangle-mode u=rw,g=,o=
 ---
-members:
+members: {}
 usernames: []
 clients: []
 #+END_SRC
@@ -6105,7 +6094,7 @@ sub dump_members_yaml ($$) {
       print $O "- $user\n";
     }
   } else {
-    print $O "members:\n";
+    print $O "members: {}\n";
     print $O "usernames: []\n";
   }
   if (@{$yaml->{"clients"}}) {
@@ -6198,15 +6187,17 @@ if (defined $ARGV[0] && $ARGV[0] eq "new") {
   my $core = `mkpasswd -m sha-512 "$epass"`; chomp $core;
   my $vault = strip_vault `ansible-vault encrypt_string "$epass"`;
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-           " playbooks/nextcloud-new.yml",
-           " -e user=$user", " -e pass=\"$epass\"");
+           "playbooks/nextcloud-new.yml",
+           "-e user=$user", "-e pass=\"$epass\"",
+           ">/dev/null");
   $members->{$user} = { "status" => "current",
                        "password_front" => $front,
                        "password_core" => $core,
                        "password_fetchmail" => $vault };
   write_members_yaml $yaml;
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-            " -t accounts -l core,front playbooks/site.yml");
+           "-t accounts -l core,front playbooks/site.yml",
+           ">/dev/null");
   exit;
 }
 
@@ -6411,10 +6402,12 @@ if (defined $ARGV[0] && $ARGV[0] eq "pass") {
 
   mysystem ("ansible-playbook -e \@Secret/become.yml",
            "playbooks/nextcloud-pass.yml",
-           "-e user=$user", "-e \"pass=$epass\"");
+           "-e user=$user", "-e \"pass=$epass\"",
+           ">/dev/null");
   write_members_yaml $mem_yaml;
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-           "-t accounts playbooks/site.yml");
+           "-t accounts playbooks/site.yml",
+           ">/dev/null");
   my $O = new IO::File;
   open ($O, "| sendmail $user\@$domain_priv")
     or die "Could not pipe to sendmail: $!\n";
@@ -6541,11 +6534,13 @@ if (defined $ARGV[0] && $ARGV[0] eq "old") {
   die "$user: does not exist\n" if ! defined $member;
 
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-           "playbooks/nextcloud-old.yml -e user=$user");
+           "playbooks/nextcloud-old.yml -e user=$user",
+           ">/dev/null");
   $member->{"status"} = "former";
   write_members_yaml $yaml;
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-           "-t accounts playbooks/site.yml");
+           "-t accounts playbooks/site.yml",
+           ">/dev/null");
   exit;
 }
 #+END_SRC
@@ -6635,8 +6630,7 @@ if (defined $ARGV[0] && $ARGV[0] eq "client") {
   } else {
     die "usage: $0 client [debian|android|campus]\n";
   }
-  my $yaml;
-  $yaml = read_members_yaml;
+  my $yaml = read_members_yaml;
   my $members = $yaml->{"members"};
   my $member = $members->{$user};
   die "$user: does not exist\n"
@@ -6849,7 +6843,7 @@ site at [[https://www.virtualbox.org/manual/UserManual.html]].
 
 The networks used in the test:
 
-- ~premises~ :: A NAT Network, simulating the cloud provider's and
+- ~public~ :: A NAT Network, simulating the cloud provider's and
   campus ISP's networks.  This is the only network with DHCP and DNS
   services provided by the hypervisor.  It is not the default NAT
   network because ~gate~ and ~front~ need to communicate.
@@ -6867,7 +6861,7 @@ The networks used in the test:
   connect the host to ~front~.
 
 In this simulation the IP address for ~front~ is not a public address
-but a private address on the NAT network ~premises~.  Thus ~front~ is
+but a private address on the NAT network ~public~.  Thus ~front~ is
 not accessible by the host, by Ansible on the administrator's
 notebook.  To work around this restriction, ~front~ gets a second
 network interface connected to the ~vboxnet2~ network.  The address of
@@ -6877,10 +6871,10 @@ The networks described above are created and "started" with the
 following ~VBoxManage~ commands.
 
 #+BEGIN_SRC sh
-VBoxManage natnetwork add --netname premises \
+VBoxManage natnetwork add --netname public \
                           --network 192.168.15.0/24 \
                           --enable --dhcp on --ipv6 off
-VBoxManage natnetwork start --netname premises
+VBoxManage natnetwork start --netname public
 VBoxManage hostonlyif create # vboxnet0
 VBoxManage hostonlyif ipconfig vboxnet0 --ip=192.168.56.10
 VBoxManage hostonlyif create # vboxnet1
@@ -6889,8 +6883,11 @@ VBoxManage hostonlyif create # vboxnet2
 VBoxManage hostonlyif ipconfig vboxnet2 --ip=192.168.58.1
 #+END_SRC
 
-Note that only the NAT network ~premises~ should have a DHCP server
-enabled.
+Note that only the NAT network ~public~ should have a DHCP server
+enabled, and it should not lease ~192.168.15.3~.  This works, so far.
+The VirtualBox DHCP service seems to start assigning IPs beginning
+with ~192.168.15.5~.  It is not simply disabled because Gate is
+expecting the service from its ISP.
 
 Note also that actual ISPs and clouds will provide Gate and Front with
 public network addresses.  In this simulation "they" provide addresses
@@ -7119,13 +7116,39 @@ Ansible's public SSH key.
 <<test-auth>>
 #+END_SRC
 
-Next, the "extra" network interface is configured with a static IP
-address.
+Next, the network interfaces are configured with static IP addresses.
+In actuality, Front gets no network configuration tweaks.  The Debian
+12 default is to broadcast for a DHCP lease on the primary NIC.  This
+works in the cloud, which should respond with an offer, though it must
+offer the public, DNS-registered, hard-coded ~front_addr~.
+
+For testing purposes, the preparation of ~front~ replaces the default
+=/etc/network/interfaces= with a new configuration that statically
+assigns ~front_addr~ to the primary NIC and a testing subnet address
+to the second NIC.
 
 #+CAPTION: [[file:private/test-front-prep][=private/test-front-prep=]]
 #+BEGIN_SRC sh :tangle private/test-front-prep :tangle-mode u=rwx,g=,o=
 
-cat <<EOF | sudo tee /etc/network/interfaces.d/enp0s8 >/dev/null
+( cd /etc/network/; \
+  [ -f interfaces~ ] || sudo mv interfaces interfaces~ )
+cat <<EOF | sudo tee /etc/network/interfaces >/dev/null
+# This file describes the network interfaces available on your system
+# and how to activate them. For more information, see interfaces(5).
+
+source /etc/network/interfaces.d/*
+
+# The loopback network interface
+auto lo
+iface lo inet loopback
+
+# The primary network interface
+auto enp0s3
+iface enp0s3 inet static
+    address 192.168.15.3/24
+    gateway 192.168.15.1
+
+# Testing interface
 auto enp0s8
 iface enp0s8 inet static
     address 192.168.58.3/24
@@ -7151,12 +7174,12 @@ With the preparatory script successfully executed, ~front~ is shut
 down and moved to the simulated cloud (from the default NAT network).
 
 The following ~VBoxManage~ commands effect the move, connecting the
-primary NIC to ~premises~ and a second NIC to the host-only network
+primary NIC to ~public~ and a second NIC to the host-only network
 ~vboxnet2~ (making it directly accessible to the administrator's
 notebook as described in [[*The Test Networks][The Test Networks]]).
 
 #+BEGIN_SRC sh
-VBoxManage modifyvm front --nic1 natnetwork --natnetwork1 premises
+VBoxManage modifyvm front --nic1 natnetwork --natnetwork1 public
 VBoxManage modifyvm front --nic2 hostonly --hostonlyadapter2 vboxnet2
 #+END_SRC
 
@@ -7252,7 +7275,7 @@ wild Ethernet (e.g. campus wireless access points, IoT, whatnot).
 VBoxManage modifyvm gate --mac-address1=080027f31679
 VBoxManage modifyvm gate --nic1 hostonly --hostonlyadapter1 vboxnet0
 VBoxManage modifyvm gate --mac-address2=0800273d42e5
-VBoxManage modifyvm gate --nic2 natnetwork --natnetwork2 premises
+VBoxManage modifyvm gate --nic2 natnetwork --natnetwork2 public
 VBoxManage modifyvm gate --mac-address3=0800274aded2
 VBoxManage modifyvm gate --nic3 hostonly --hostonlyadapter3 vboxnet1
 #+END_SRC
@@ -7263,7 +7286,7 @@ values of the MAC address variables in this table.
 | device   | network    | simulating      | MAC address variable |
 |----------+------------+-----------------+----------------------|
 | ~enp0s3~ | ~vboxnet0~ | campus Ethernet | ~gate_lan_mac~       |
-| ~enp0s8~ | ~premises~ | campus ISP      | ~gate_isp_mac~       |
+| ~enp0s8~ | ~public~   | campus ISP      | ~gate_isp_mac~       |
 | ~enp0s9~ | ~vboxnet1~ | campus IoT      | ~gate_wild_mac~      |
 
 ~gate~ is now prepared for configuration by Ansible.
@@ -7377,6 +7400,18 @@ To configure the test machines, the ~./inst config~ command is
 executed.  Note that this first run should exercise all of the
 handlers, /and/ that subsequent runs probably /do not/.
 
+Presumably the ~./inst config~ command completed successfully, but
+before testing begins, ~gate~ is restarted.  Basic networking tests
+will fail unless the interfaces on ~gate~ are renamed, and nothing
+less than a restart will get ~systemd-udevd~ to apply the installed
+=.link= files.
+
+# Does this work???
+# udevadm control --reload
+# udevadm trigger -s net -c add -a address=08:00:27:f3:16:79
+# udevadm trigger -s net -c add -a address=08:00:27:4a:de:d2
+# udevadm trigger -s net -c add -a address=08:00:27:3d:42:e5
+
 ** Test Basics
 
 At this point the test institute is just ~core~, ~gate~ and ~front~,
@@ -7394,7 +7429,7 @@ forwarding (and NATing).  On ~core~ (and ~gate~):
 
 #+BEGIN_SRC sh
 ping -c 1 8.8.4.4      # dns.google
-ping -c 1 192.168.15.5 # front_addr
+ping -c 1 192.168.15.3 # front_addr
 #+END_SRC
 
 ~gate~ and thus ~core~ should be able to resolve internal and public
@@ -7427,7 +7462,7 @@ instant attention).
 ** The Test Nextcloud
 
 Further tests involve Nextcloud account management.  Nextcloud is
-installed on ~core~ as described in [[*Configure Nextcloud][Configure Nextcloud]].  Once
+installed on ~core~ as described in [[*Install Nextcloud][Install Nextcloud]].  Once
 =/Nextcloud/= is created, ~./inst config core~ will validate
 or update its configuration files.
 
@@ -7681,11 +7716,11 @@ Outgoing email is also tested.  A message to
 
 At this point, ~dick~ can move abroad, from the campus Wi-Fi
 (host-only network ~vboxnet1~) to the broader Internet (the NAT
-network ~premises~).  The following command makes the change.  The
+network ~public~).  The following command makes the change.  The
 machine does not need to be shut down.
 
 #+BEGIN_SRC s
-VBoxManage modifyvm dick --nic1 natnetwork --natnetwork1 premises
+VBoxManage modifyvm dick --nic1 natnetwork --natnetwork1 public
 #+END_SRC
 
 Then the campus VPN is disconnected and the public VPN connected.
@@ -7819,7 +7854,7 @@ seen.
 - Find it in =/home/dick/Maildir/new/=.
 - Re-configure Evolution on ~dick~.  Edit the ~dick@small.example.org~
   mail account (or create a new one?) so that the Receiving Email
-  Server name is ~192.168.15.5~, not ~mail.small.private~.  The
+  Server name is ~192.168.15.3~, not ~mail.small.private~.  The
   latter domain name will not work while the campus is disappeared.
   In actual use (with Front, not ~front~), the institute domain name
   could be used.
diff --git a/inst b/inst
index f025af29e6889602967343ec0b7168ea56a3d373..b407c137bd01be068bacd3e9edcedca64e27318f 100755 (executable)
--- a/inst
+++ b/inst
@@ -88,28 +88,28 @@ if (defined $ARGV[0] && $ARGV[0] eq "CA") {
 
   mysystem "mkdir --mode=700 Secret/root.gnupg";
   mysystem ("gpg --homedir Secret/root.gnupg",
-           " --batch --quick-generate-key --passphrase ''",
-           " root\@core.$pvt");
+           "--batch --quick-generate-key --passphrase ''",
+           "root\@core.$pvt");
   mysystem ("gpg --homedir Secret/root.gnupg",
-           " --export --armor --output Secret/root-pub.pem",
-           " root\@core.$pvt");
+           "--export --armor --output Secret/root-pub.pem",
+           "root\@core.$pvt");
   chmod 0440, "root-pub.pem";
   mysystem ("gpg --homedir Secret/root.gnupg",
-           " --export-secret-key --armor --output Secret/root-sec.pem",
-           " root\@core.$pvt");
+           "--export-secret-key --armor --output Secret/root-sec.pem",
+           "root\@core.$pvt");
   chmod 0400, "root-sec.pem";
 
   mysystem "mkdir Secret/ssh_admin";
   chmod 0700, "Secret/ssh_admin";
-  mysystem ("ssh-keygen -q -t rsa"
-           ." -C A\\ Small\\ Institute\\ Administrator",
-           " -N '' -f Secret/ssh_admin/id_rsa");
+  mysystem ("ssh-keygen -q -t rsa",
+           "-C A\\ Small\\ Institute\\ Administrator",
+           "-N '' -f Secret/ssh_admin/id_rsa");
 
   mysystem "mkdir Secret/ssh_monkey";
   chmod 0700, "Secret/ssh_monkey";
   mysystem "echo 'HashKnownHosts  no' >Secret/ssh_monkey/config";
   mysystem ("ssh-keygen -q -t rsa -C monkey\@core",
-           " -N '' -f Secret/ssh_monkey/id_rsa");
+           "-N '' -f Secret/ssh_monkey/id_rsa");
 
   mysystem "mkdir Secret/ssh_front";
   chmod 0700, "Secret/ssh_front";
@@ -186,7 +186,7 @@ sub dump_members_yaml ($$) {
       print $O "- $user\n";
     }
   } else {
-    print $O "members:\n";
+    print $O "members: {}\n";
     print $O "usernames: []\n";
   }
   if (@{$yaml->{"clients"}}) {
@@ -249,15 +249,17 @@ if (defined $ARGV[0] && $ARGV[0] eq "new") {
   my $core = `mkpasswd -m sha-512 "$epass"`; chomp $core;
   my $vault = strip_vault `ansible-vault encrypt_string "$epass"`;
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-           " playbooks/nextcloud-new.yml",
-           " -e user=$user", " -e pass=\"$epass\"");
+           "playbooks/nextcloud-new.yml",
+           "-e user=$user", "-e pass=\"$epass\"",
+           ">/dev/null");
   $members->{$user} = { "status" => "current",
                        "password_front" => $front,
                        "password_core" => $core,
                        "password_fetchmail" => $vault };
   write_members_yaml $yaml;
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-            " -t accounts -l core,front playbooks/site.yml");
+           "-t accounts -l core,front playbooks/site.yml",
+           ">/dev/null");
   exit;
 }
 
@@ -320,10 +322,12 @@ if (defined $ARGV[0] && $ARGV[0] eq "pass") {
 
   mysystem ("ansible-playbook -e \@Secret/become.yml",
            "playbooks/nextcloud-pass.yml",
-           "-e user=$user", "-e \"pass=$epass\"");
+           "-e user=$user", "-e \"pass=$epass\"",
+           ">/dev/null");
   write_members_yaml $mem_yaml;
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-           "-t accounts playbooks/site.yml");
+           "-t accounts playbooks/site.yml",
+           ">/dev/null");
   my $O = new IO::File;
   open ($O, "| sendmail $user\@$domain_priv")
     or die "Could not pipe to sendmail: $!\n";
@@ -346,11 +350,13 @@ if (defined $ARGV[0] && $ARGV[0] eq "old") {
   die "$user: does not exist\n" if ! defined $member;
 
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-           "playbooks/nextcloud-old.yml -e user=$user");
+           "playbooks/nextcloud-old.yml -e user=$user",
+           ">/dev/null");
   $member->{"status"} = "former";
   write_members_yaml $yaml;
   mysystem ("ansible-playbook -e \@Secret/become.yml",
-           "-t accounts playbooks/site.yml");
+           "-t accounts playbooks/site.yml",
+           ">/dev/null");
   exit;
 }
 
@@ -375,8 +381,7 @@ if (defined $ARGV[0] && $ARGV[0] eq "client") {
   } else {
     die "usage: $0 client [debian|android|campus]\n";
   }
-  my $yaml;
-  $yaml = read_members_yaml;
+  my $yaml = read_members_yaml;
   my $members = $yaml->{"members"};
   my $member = $members->{$user};
   die "$user: does not exist\n"
index c0138d8b5622e8ef927addf88c47a6d294781c56..34d8734eb6d456c8911048a370435315b5b4090d 100644 (file)
@@ -4,7 +4,7 @@ PostUp = wg set %i private-key /etc/wireguard/private-key
 
 # Front
 [Peer]
-EndPoint = 192.168.15.5:39608
+EndPoint = 192.168.15.3:39608
 PublicKey = S+6HaTnOwwhWgUGXjSBcPAvifKw+j8BDTRfq534gNW4=
 AllowedIPs = 10.177.87.1
 AllowedIPs = 10.177.87.0/24
index 5635a85ef9f30ede5fea993c6d39a40865d759f1..0c48a4aa4a671946fb38bace5188ee0f111b6012 100644 (file)
@@ -1,4 +1,4 @@
 ---
-members:
+members: {}
 usernames: []
 clients: []
index ec65ed60d845d9e58cc2ddc04e43a8ecb41d8a63..69b3574260686b0c9308dfde5b04c5d37b08219a 100755 (executable)
@@ -24,7 +24,25 @@ sudo apt install wireguard systemd-resolved \
     echo " A Small Institute Administrator" ) \
   >>.ssh/authorized_keys )
 
-cat <<EOF | sudo tee /etc/network/interfaces.d/enp0s8 >/dev/null
+( cd /etc/network/; \
+  [ -f interfaces~ ] || sudo mv interfaces interfaces~ )
+cat <<EOF | sudo tee /etc/network/interfaces >/dev/null
+# This file describes the network interfaces available on your system
+# and how to activate them. For more information, see interfaces(5).
+
+source /etc/network/interfaces.d/*
+
+# The loopback network interface
+auto lo
+iface lo inet loopback
+
+# The primary network interface
+auto enp0s3
+iface enp0s3 inet static
+    address 192.168.15.3/24
+    gateway 192.168.15.1
+
+# Testing interface
 auto enp0s8
 iface enp0s8 inet static
     address 192.168.58.3/24
index fe1affde08adae6788ee7d1c3d639edeec86b149..1d3e1959ae80715f0fb9b7d8e1dd64784c7a1c57 100644 (file)
@@ -46,7 +46,7 @@ front_wg_addr:
 
 core_lan_mac:               08:00:27:b3:e5:5f
 
-nextcloud_dbpass:           ippAgmaygyob
+nextcloud_dbpass:           ippAgmaygyobwyt5
 
 nextcloud_region:           US
 
index f61b4af1e6cef3ff50bd10bb1600e6acefc97cc8..5a72f1f00c5df0e85541c3dd72f5d3abb93cea2a 100644 (file)
@@ -1,6 +1,6 @@
 ---
 domain_name: small.example.org
 
-front_addr: 192.168.15.5
+front_addr: 192.168.15.3
 
 full_name: Small Institute LLC
index f7cf1ce537afd905aa0e2eb8f005df308c1b55e4..1266c4211af3178c5684e27e6de166a569156919 100644 (file)
         admin:         root
         www-data:      root
         monkey:                root
+        root:          {{ ansible_user }}
     path: /etc/aliases
     marker: "# {mark} INSTITUTE MANAGED BLOCK"
   notify: New aliases.
index 9b6120de07665377ccaaa7a7d914f666acee31bd..a4dc4cfac0358f225a8175bdb28eff8864ccfbf8 100644 (file)
@@ -23,7 +23,7 @@
 - name: Update hostname.
   become: yes
   command: hostname -F /etc/hostname
-  when: domain_name != ansible_hostname
+  when: domain_name != ansible_fqdn
   tags: actualizer
 
 - name: Add {{ ansible_user }} to system groups.
     src: /home/{{ item }}/Public/HTML
     state: link
     force: yes
+    follow: false
   loop: "{{ usernames }}"
   when: members[item].status == 'current'
   tags: accounts
index 4320a35e7a2533fd7b4409a52b58c1035d322bb4..ce1b4ddc91e31b233b3bcb661a7a21c63d919d60 100644 (file)
@@ -97,7 +97,7 @@
   - { line: "DEFAULT_FORWARD_POLICY=\"DROP\"",
       regexp: "^DEFAULT_FORWARD_POLICY=" }
 
-- name: Configure UFW NAT rules.
+- name: Configure UFW rules.
   become: yes
   blockinfile:
     block: |
       -A POSTROUTING -s {{ private_net_cidr }} -o isp -j MASQUERADE
       -A POSTROUTING -s {{    wild_net_cidr }} -o isp -j MASQUERADE
       COMMIT
+      *filter
+      -A ufw-before-forward -i lan  -o isp -j ACCEPT
+      -A ufw-before-forward -i wild -o isp -j ACCEPT
+      -A ufw-before-forward -i lan  -o wg0 -j ACCEPT
+      -A ufw-before-forward -i wg0  -o lan -j ACCEPT
+      -A ufw-before-forward -i wg0  -o wg0 -j ACCEPT
+      COMMIT
     dest: /etc/ufw/before.rules
     insertafter: EOF
     prepend_newline: yes
 
-- name: Configure UFW FORWARD rules.
+- name: Enable UFW.
   become: yes
-  blockinfile:
-    block: |
-      *filter
-      -A ufw-user-forward -i lan  -o isp -j ACCEPT
-      -A ufw-user-forward -i wild -o isp -j ACCEPT
-      -A ufw-user-forward -i lan  -o wg0 -j ACCEPT
-      -A ufw-user-forward -i wg0  -o lan -j ACCEPT
-      -A ufw-user-forward -i wg0  -o wg0 -j ACCEPT
-      COMMIT
-    dest: /etc/ufw/user.rules
-    insertafter: EOF
-    prepend_newline: yes
+  ufw: state=enabled
+  tags: actualizer
 
 - name: Enable IP forwarding.
   become: yes
index efa30a2da0de9aec48409f919a183b50385743c9..643a9217e3ed3979fc79a81c76d4db2a21d16457 100644 (file)
@@ -15,5 +15,5 @@ SMTP={{ core_addr }}
 
 [DHCPServerStaticLease]
 MACAddress={{ wild.MAC }}
-Address={{ wild.num |ansible.utils.ipaddr('address') }}
+Address={{ wild_net_cidr |ansible.utils.ipaddr(wild.num) }}
 {% endfor %}