| … | … | @@ -9,7 +9,14 @@ PROXY_CONF="/etc/apache2/7rnx-proxy.conf" |
| 9 | 9 | |
| 10 | 10 | echo "=== Step 1: Sudoers rules ===" |
| 11 | 11 | |
| 12 | | sudo tee /etc/sudoers.d/7rnx-proxy > /dev/null << 'EOF' |
| 12 | # Stage to a temp file, VALIDATE, then install. Never write /etc/sudoers.d |
| 13 | # directly: this block used to `tee` straight to the live path and only run |
| 14 | # `visudo -c` afterwards, so a malformed write was already installed by the time |
| 15 | # it was caught. That is exactly how the live file ended up containing a stray |
| 16 | # `EOF` + `sudo chmod ...` (a paste where the heredoc delimiter never closed), |
| 17 | # emitting a syntax error on every sudo call for weeks. Validate first. |
| 18 | SUDOERS_TMP="$(mktemp)" |
| 19 | cat > "$SUDOERS_TMP" << 'EOF' |
| 13 | 20 | # Allow fleeky to deploy proxy config and reload Apache (no password) |
| 14 | 21 | fleeky ALL=(root) NOPASSWD: /bin/cp /tmp/7rnx-proxy.conf /etc/apache2/7rnx-proxy.conf |
| 15 | 22 | # Host-routed vhosts (vhost mode) — a top-level sites-enabled file (VirtualHost blocks). |
| … | … | @@ -18,7 +25,17 @@ fleeky ALL=(root) NOPASSWD: /usr/sbin/apachectl configtest |
| 18 | 25 | fleeky ALL=(root) NOPASSWD: /bin/systemctl reload apache2 |
| 19 | 26 | EOF |
| 20 | 27 | |
| 21 | | sudo chmod 0440 /etc/sudoers.d/7rnx-proxy |
| 28 | if ! sudo visudo -c -f "$SUDOERS_TMP"; then |
| 29 | rm -f "$SUDOERS_TMP" |
| 30 | echo "Sudoers: STAGED FILE IS INVALID — refusing to install. Live file untouched." >&2 |
| 31 | exit 1 |
| 32 | fi |
| 33 | |
| 34 | # install(1) is atomic and sets owner/mode in one step, so there is no window |
| 35 | # where the file exists with the wrong permissions (sudo ignores a sudoers.d |
| 36 | # file that is group/world writable). |
| 37 | sudo install -m 0440 -o root -g root "$SUDOERS_TMP" /etc/sudoers.d/7rnx-proxy |
| 38 | rm -f "$SUDOERS_TMP" |
| 22 | 39 | sudo visudo -c -f /etc/sudoers.d/7rnx-proxy |
| 23 | 40 | echo "Sudoers: OK" |
| 24 | 41 | |