eletrotupi / tcc/ commit / d0ab993

deploy: give the containers readable configs and force the nginx reload

valkey.conf was owned by the deploy user with no read for the unprivileged
user the valkey image drops to, and the logs htpasswd was unreadable by nginx
workers, so /logs failed. Both are readable now.

The nginx play forces its handlers and validates the config with nginx -t, so a
failure earlier in the run can no longer leave the vhost updated but not
reloaded.
Pedro Lucas Porcellis porcellis@eletrotupi.com · 13 days ago d0ab9930b8d2efe12277e2365410dade4162f9c5 Browse files
Parents 723aa5b
Changed files
4
Additions
+15
Deletions
-2
ansible/cert.yml modified+1
ansible/cert.yml
1 1
---
2 2
# ansible/cert.yml
3 3
# Installs uacme and manages certificates as the unprivileged `acme` user
4 4
#
5 5
# Registration is interactive and must be done by hand once: see the debug
9 9

10 10
- name: Provision ACME certificates
11 11
  hosts: vps
12 12
  become: yes
13 13
  become_method: doas
14 +
  force_handlers: true
14 15
  vars_files:
15 16
    - vars/vhosts.yml
16 17

17 18
  roles:
18 19
    - uacme
ansible/deploy.yml modified+3
ansible/deploy.yml
1 1
---
2 2
# ansible/deploy.yml
3 3
# Publishes the nginx vhost (two-phase around the ACME certificate)
4 4
#
5 5
#   ansible-playbook -i inventory/hosts.yml deploy.yml --ask-become-pass
6 6

7 7
- name: Configure nginx
8 8
  hosts: vps
9 9
  become: yes
10 10
  become_method: doas
11 +
  # Reload even if an earlier task failed, so a late failure cannot leave the
12 +
  # vhost changed but nginx still serving the old config
13 +
  force_handlers: true
11 14
  vars_files:
12 15
    - vars/vhosts.yml
13 16

14 17
  roles:
15 18
    - nginx
ansible/roles/app/tasks/main.yml
1 1
---
2 2
# roles/app/tasks/main.yml
3 3
# Places the production app config in /srv/app/<env>/
4 4
# The env files are rendered from group_vars (secrets come from the encrypted
5 5
# vault.yml), so there is nothing to fill in by hand anymore
30 30
    owner: "{{ deploy_user }}"
31 31
    group: "{{ deploy_user }}"
32 32
    mode: "0640"
33 33
  tags: [app]
34 34

35 +
# The valkey image drops to its own unprivileged user, so this file has to be
36 +
# readable by it. valkey.conf holds no secrets (no password), so 0644 is fine
35 37
- name: Install the valkey configuration
36 38
  ansible.builtin.copy:
37 39
    src: valkey.conf
38 40
    dest: "/srv/app/{{ app_env }}/valkey.conf"
39 41
    owner: "{{ deploy_user }}"
40 42
    group: "{{ deploy_user }}"
41 -
    mode: "0640"
43 +
    mode: "0644"
42 44
  tags: [app]
43 45

44 46
- name: Install the Vector configuration
45 47
  ansible.builtin.copy:
46 48
    src: vector.yaml
61 63
    - { src: env.j2, dest: .env }
62 64
    - { src: env.production.j2, dest: .env.production }
63 65
  loop_control:
64 66
    label: "{{ item.dest }}"
65 67
  tags: [app]
ansible/roles/nginx/tasks/main.yml
1 1
---
2 2
# roles/nginx/tasks/main.yml
3 3
# Publishes the vhost, two-phase around the ACME certificate
4 4
#
5 5
#   deploy.yml (this role) will HTTP-only block, then obtain cert via the wrapper then
49 49
- name: Install the logs UI htpasswd file
50 50
  ansible.builtin.copy:
51 51
    dest: "{{ nginx_logs_htpasswd_file }}"
52 52
    content: "{{ nginx_logs_htpasswd }}\n"
53 53
    owner: root
54 -
    group: root
54 +
    # nginx workers run unprivileged and must be able to read this
55 +
    group: nginx
55 56
    mode: "0640"
56 57
  notify: reload nginx
57 58
  tags: [nginx]
58 59

59 60
- name: Check whether the certificate exists
96 97
    src: site.https.j2
97 98
    dest: "{{ nginx_conf_dir }}/{{ vhosts[0] }}.conf"
98 99
    mode: "0644"
99 100
  notify: reload nginx
100 101
  when: nginx_cert_after.stat.exists
102 +
  tags: [nginx]
103 +

104 +
- name: Validate the nginx configuration
105 +
  ansible.builtin.command:
106 +
    cmd: nginx -t
107 +
  changed_when: false
101 108
  tags: [nginx]
102 109

103 110
- name: Explain the manual step when no certificate is available yet
104 111
  ansible.builtin.debug:
105 112
    msg: |-
107 114
      run this once by hand and then re-run deploy.yml:
108 115

109 116
        doas -u acme uacme -v -h /usr/share/uacme/uacme.sh new {{ vhosts[0] }}
110 117
  when: not nginx_cert_after.stat.exists
111 118
  tags: [nginx]