diff --git a/ansible/group_vars/all/openapply.yml b/ansible/group_vars/all/openapply.yml index 4722bf8..51f61e8 100644 --- a/ansible/group_vars/all/openapply.yml +++ b/ansible/group_vars/all/openapply.yml @@ -1,8 +1,8 @@ --- # Proxmox API settings (credentials come from vault variables) -openapply_pve_api_host: "{{ vault_proxmox_api_host | default('') }}" -openapply_pve_api_user: "{{ vault_proxmox_api_user | default('') }}" -openapply_pve_api_token_id: "{{ vault_proxmox_api_token_id | default('') }}" +openapply_pve_api_host: "{{ vault_proxmox_api_host | default('10.0.0.201') }}" +openapply_pve_api_user: "{{ vault_proxmox_api_user | default('root@pam') }}" +openapply_pve_api_token_id: "{{ vault_proxmox_api_token_id | default('automation', true) }}" openapply_pve_api_token_secret: "{{ vault_proxmox_api_token_secret | default('') }}" openapply_proxmox_validate_certs: false @@ -10,7 +10,7 @@ openapply_proxmox_validate_certs: false openapply_pve_node: pve01 openapply_lxc_vmid: 105 openapply_lxc_hostname: openapply-prod -openapply_lxc_template: local:vztmpl/ubuntu-24.04-standard_24.04-1_amd64.tar.zst +openapply_lxc_template: local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst openapply_lxc_storage: local-lvm openapply_lxc_cores: 2 openapply_lxc_memory_mb: 4096 @@ -18,7 +18,7 @@ openapply_lxc_swap_mb: 512 openapply_lxc_unprivileged: true openapply_lxc_onboot: true openapply_lxc_features: - nesting: 1 + - nesting=1 # LXC networking openapply_lxc_bridge: vmbr0 @@ -31,7 +31,12 @@ openapply_lxc_nic_firewall: true openapply_use_proxmox_nic: false # LXC credentials (from vault) -openapply_lxc_password: "{{ vault_openapply_lxc_root_password | default('') }}" +openapply_lxc_password: "{{ vault_openapply_lxc_root_password | default(vault_proxmox_root_password | default('')) }}" # Controller runtime preflight openapply_validate_controller_python_deps: true + +# Application runtime toggles for first deployment +openapply_app_install_firebase_cli: false +openapply_app_repo_version: master +openapply_app_force_rebuild: true diff --git a/ansible/group_vars/all/vault.yml b/ansible/group_vars/all/vault.yml index 08b2c48..c5db4ed 100644 --- a/ansible/group_vars/all/vault.yml +++ b/ansible/group_vars/all/vault.yml @@ -1,45 +1,48 @@ $ANSIBLE_VAULT;1.1;AES256 -38356633393935376433623034326666613132646638323438396364636534323630623562633138 -3837303132383437356638613338636562393563376430310a366234366565313739653035306265 -61303534336437393138353063383138333163303233316238633832616561383731626164383731 -3330363738323538350a343335326162393264636332303633663934653432326538373466353036 -38353064383165303331323134396366326162333432656636626261376332646130353661613032 -64343439336266616230326139643230663265626333386634653566316336613565303332633965 -39333934623835353635393638643062386238313933616535663566646532643735343865393563 -39373235366161346162663263623762306630663935663538396432343664353262333836303235 -30383261663366653064663639313336376137386465326331346337356431663030666335363232 -36346166373031323934303262623932316131656632306534353561623338653362613636393565 -66346163383530633161663464303561383539613962306166333031636135626431616465373566 -33613732646334353365303338643665353138383631646361653738653831666433373639326566 -36643864636132383264376162353736333761666239346338333032663764386665663666373037 -37333263373934386261356261373731313735643838656539396162306236663630333835343934 -62643431333938623137633666653564616539343339323639373436613466643165376237653732 -62316663306664366562636263326639623334356630323764646430333265666339373661356237 -34323361373430633332363639393961313036303364313366323431646339356630303562613234 -35643763656233633833343236303865656664636432663434653437353564376137363335353564 -30656361666235393563613063316639373065336530616261363664343630663735626636653230 -63613761666132656233323336616665393761396362326234613239623961316133646161653563 -38346532626261396263623235346161346435653732616561633866633265313931393962303332 -30363735356166336233633466663234306532646531393330333033653065626465306263383238 -61623733373030626364373030633036366633356134613562663231666164373763376336333936 -34646562303565393032343033313935323266333832306536343438663034326562616339663436 -34623161326632623263303236336561313761353962333335313930383531616532393033343336 -36316334393165393839313836626239643935636233343265363734623732313136313965326262 -32376131653065336632306330643164633239623431323763616434393535653730373139613361 -34386663393262363734333230366636633963653230613163343937666330626363643335383033 -62393530303765643463626436326331346163353332386662363537656630353538383430373534 -39623134323333363239353939336530643564346139613139666431636265393134383538613632 -34383364366266656164313466643835386361363762613962383832623932393837393939386639 -37616236386631326136356131366162336566663634346233353063396164666262396163616331 -33353562663961313832643066623735386233356333313939383638633939333838643666636135 -34623733303432383261383765306438333961306161386461646437386438326133386662386630 -65326436346166643334356136313837306162343639343362313937313235356432326466393532 -62653637633964343530346665363564343632353037323465363166643334623531306365363966 -36303462333164626234386465373332333263323730386565303637613561643963633066336635 -62643730343465616230383234653365643637653765666639646433313539646631656637363239 -65653263616237663134376465343636323865316462323734346166633262393163616662333430 -37323266353332386131633930303131313338663164623234333263663837303263626237343266 -61646638343565356637316639613635363636656362363463616166386465623461663433333436 -35613365326331303763326334323831313335373937613261643935373939383538303231376533 -33343837643233353063343434623930333238653533383665363537393533323131323764396231 -38386438653162336366 +35313963633335346336316139656531613164666132623362393137333034303438643063613861 +3964373430656434376362396361633338363363326565640a306365353965643433643333316438 +39653236656561303033343766663865616434656631666439626238616330386132663939353962 +3339393130396634300a613065306536643133353837646666366565303466633963386533323732 +30626338336562666333323332616533666634323833333563333938666132313163393462336236 +35656161623036333639626565646463366533613633663031643363353035303165383465656230 +34616662633262636630346438356261656234623965616330356639383166623533386439366336 +62363665313265383761376636653432343234663363303630656630643432623730343264633638 +62646461313937646365656631363162653737626265386561383937656437663637306263613363 +33616363666435323733356430323632373762626364396131393366646330373834656263363463 +66343961623438623239383437306364663362396238346465623630373939633830333361393235 +39633537323366313136306264663830626438616434663430353936303661323665376237353335 +36336135376632386231313030356465353665613930303437313564636130636336316431633663 +36646430323236336634323730366533656364333935373161353939613761623331633138653062 +66323536323139373837313433393065316163353030383536326531323137393833633465333432 +38366563303463616365353064383161323334356530306431613862613631376461643438613733 +36333164643165623864616631653432633961383035303331313339373337326661306238343063 +63363665646139393363643038353230626465343336393865303062373261306531336164643638 +66346163336236383131333237366630383964633334323461303330356465353937343535343032 +37613961303861646266333162303731383962333562393035663239623539306230316134613239 +61346234323038656237646661353663363262383965653637356663653966633664383430373363 +33313332666138353939656266353134396633616364636333376232613230336361326265366265 +66656334613435663432646165383262616636633232643230353434653237646133636361656639 +36623564373835393862343330336361336432333834363234376534376132353165626134323135 +31383030626362343034303838656631393565666330646465323434326434383466646164653935 +30653235633262313537333733396464633238313830326633376436323364636337393263666630 +65323830396138663761383832386264336534633961653837656432336366346439306134316235 +65343163636364653262396364356233653533333363396339633564643831383733663863393632 +33326262653438366435646337373638393238343039626533363239366366373663616366643365 +39303837623835643831633066303861633930396566663261616132353933306237353561313563 +39623732323566303937636133336665386231383637396565343430393232636230393638303138 +35326565373936616666613635316239346535656463356531393830303230303033663031303339 +65623433663230343639643033363666393264613964386134383230363030373232373637303836 +30623461633062303039663331343134323264326264386462336566666330386130313039313635 +33336435623938656435633432323536323064323262623832313764366466396465306338303038 +35343131393132333664313563393662663761643265333937373136326563396535356461316562 +63323335343266653565303037386463396131613133663835396531353064396265353031396664 +38393131613430623330323038313062626334666161656665633934336163666533376134373831 +66323563323765643532653864306335323463376363346662353033666138386638643564616333 +38643932616530623164363663333437346333346465363634633532313931623138613134343338 +62333333393166323039373163623033613736303066616364376432393830343262613661633831 +66653661353738646439356661376161623061313334656165303736313262616563323361333535 +33636261313436663961343162326664366461633263633736363634323163366135666362383166 +37633435373335343434653865613336333765663334643230663330646536633835393336333563 +64373434386464656137343835633165353637373830313030626235396162653035326361623431 +63346165643938643638313439383734666236343266333836303130353634626234656430633138 +313532626665646362623037353863656235 diff --git a/ansible/playbooks/deploy-openapply.yml b/ansible/playbooks/deploy-openapply.yml index 14bf1c7..ad85c56 100644 --- a/ansible/playbooks/deploy-openapply.yml +++ b/ansible/playbooks/deploy-openapply.yml @@ -3,6 +3,7 @@ hosts: localhost gather_facts: false connection: local + become: false pre_tasks: - name: Validate required infrastructure variables @@ -26,14 +27,15 @@ group_vars/all/openapply.yml and vault variables. - name: Validate Proxmox Python dependencies on controller - ansible.builtin.command: python3 -c "import proxmoxer, requests" + ansible.builtin.command: "{{ ansible_playbook_python }} -c 'import proxmoxer, requests'" register: openapply_controller_python_deps changed_when: false failed_when: openapply_controller_python_deps.rc != 0 + become: false when: openapply_validate_controller_python_deps | bool tasks: - - name: Ensure OpenApply LXC is present and started + - name: Ensure OpenApply LXC is present community.proxmox.proxmox: api_host: "{{ openapply_pve_api_host }}" api_user: "{{ openapply_pve_api_user }}" @@ -54,9 +56,20 @@ netif: net0: "name=eth0,bridge={{ openapply_lxc_bridge }},ip={{ openapply_lxc_ip_cidr }},gw={{ openapply_lxc_gateway }}" features: "{{ openapply_lxc_features }}" - state: started + state: present register: openapply_lxc_status + - name: Ensure OpenApply LXC is started + community.proxmox.proxmox: + api_host: "{{ openapply_pve_api_host }}" + api_user: "{{ openapply_pve_api_user }}" + api_token_id: "{{ openapply_pve_api_token_id }}" + api_token_secret: "{{ openapply_pve_api_token_secret }}" + validate_certs: "{{ openapply_proxmox_validate_certs }}" + node: "{{ openapply_pve_node }}" + vmid: "{{ openapply_lxc_vmid }}" + state: started + - name: Reconcile LXC NIC configuration via Proxmox API when: openapply_use_proxmox_nic | bool block: @@ -86,6 +99,8 @@ ansible_host: "{{ openapply_lxc_management_ip }}" ansible_user: "{{ openapply_lxc_ssh_user }}" ansible_port: "{{ openapply_lxc_ssh_port }}" + ansible_password: "{{ openapply_lxc_password }}" + ansible_ssh_pass: "{{ openapply_lxc_password }}" ansible_python_interpreter: /usr/bin/python3 groups: lxc_guests diff --git a/ansible/roles/openapply_app/tasks/deploy_code.yml b/ansible/roles/openapply_app/tasks/deploy_code.yml index 95aaf7c..017abc2 100644 --- a/ansible/roles/openapply_app/tasks/deploy_code.yml +++ b/ansible/roles/openapply_app/tasks/deploy_code.yml @@ -8,8 +8,9 @@ ansible.builtin.user: name: "{{ openapply_app_service_user }}" group: "{{ openapply_app_service_group }}" + home: /home/{{ openapply_app_service_user }} shell: /usr/sbin/nologin - create_home: false + create_home: true system: true state: present @@ -21,13 +22,25 @@ group: "{{ openapply_app_service_group }}" mode: "0755" -- name: Render OpenApply environment file - ansible.builtin.template: - src: openapply.env.j2 - dest: "{{ openapply_app_root }}/.env" +- name: Check whether OpenApply directory is already a git repository + ansible.builtin.stat: + path: "{{ openapply_app_root }}/.git" + register: openapply_git_metadata + +- name: Reset OpenApply directory when not a git repository + ansible.builtin.file: + path: "{{ openapply_app_root }}" + state: absent + when: not openapply_git_metadata.stat.exists + +- name: Recreate OpenApply root directory after reset + ansible.builtin.file: + path: "{{ openapply_app_root }}" + state: directory owner: "{{ openapply_app_service_user }}" group: "{{ openapply_app_service_group }}" - mode: "0640" + mode: "0755" + when: not openapply_git_metadata.stat.exists - name: Sync OpenApply source code ansible.builtin.git: @@ -35,13 +48,21 @@ version: "{{ openapply_app_repo_version }}" dest: "{{ openapply_app_root }}" update: true - force: false + force: true accept_hostkey: true key_file: "{{ openapply_app_git_ssh_key_file | default(omit, true) }}" become: true become_user: "{{ openapply_app_service_user }}" register: openapply_repo_checkout +- name: Render OpenApply environment file + ansible.builtin.template: + src: openapply.env.j2 + dest: "{{ openapply_app_root }}/.env" + owner: "{{ openapply_app_service_user }}" + group: "{{ openapply_app_service_group }}" + mode: "0640" + - name: Check node_modules presence ansible.builtin.stat: path: "{{ openapply_app_root }}/node_modules" @@ -75,6 +96,31 @@ - openapply_repo_checkout.changed or openapply_app_force_rebuild | bool changed_when: true +- name: Check Astro dist directory + ansible.builtin.stat: + path: "{{ openapply_app_root }}/astro/dist" + register: openapply_astro_dist + +- name: Check SPA dist directory + ansible.builtin.stat: + path: "{{ openapply_app_root }}/spa/dist" + register: openapply_spa_dist + +- name: Publish SPA build under /app path for Astro runtime + ansible.builtin.shell: | + rm -rf "{{ openapply_app_root }}/astro/dist/app" + mkdir -p "{{ openapply_app_root }}/astro/dist/app" + cp -a "{{ openapply_app_root }}/spa/dist/." "{{ openapply_app_root }}/astro/dist/app/" + args: + executable: /bin/bash + become: true + become_user: "{{ openapply_app_service_user }}" + when: + - openapply_astro_dist.stat.isdir | default(false) + - openapply_spa_dist.stat.isdir | default(false) + - openapply_repo_checkout.changed or openapply_app_force_rebuild | bool + changed_when: true + - name: Install OpenApply systemd unit ansible.builtin.template: src: openapply.service.j2 diff --git a/ansible/roles/openapply_app/tasks/verify.yml b/ansible/roles/openapply_app/tasks/verify.yml index add2209..1afa98b 100644 --- a/ansible/roles/openapply_app/tasks/verify.yml +++ b/ansible/roles/openapply_app/tasks/verify.yml @@ -1,13 +1,12 @@ --- -- name: Gather service facts - ansible.builtin.service_facts: - -- name: Assert OpenApply service is running - ansible.builtin.assert: - that: - - "ansible_facts.services[openapply_app_service_name + '.service'] is defined" - - "ansible_facts.services[openapply_app_service_name + '.service'].state == 'running'" - fail_msg: "OpenApply systemd service is not running." +- name: Verify OpenApply service reaches active state + ansible.builtin.command: + cmd: "systemctl is-active {{ openapply_app_service_name }}" + register: openapply_service_state + changed_when: false + retries: 20 + delay: 3 + until: openapply_service_state.stdout | trim == 'active' - name: Wait for OpenApply port to become reachable ansible.builtin.wait_for: diff --git a/ansible/roles/openapply_app/templates/openapply.service.j2 b/ansible/roles/openapply_app/templates/openapply.service.j2 index 562f8ac..0124ab1 100644 --- a/ansible/roles/openapply_app/templates/openapply.service.j2 +++ b/ansible/roles/openapply_app/templates/openapply.service.j2 @@ -10,6 +10,8 @@ Group={{ openapply_app_service_group }} WorkingDirectory={{ openapply_app_root }} EnvironmentFile={{ openapply_app_root }}/.env ExecStart={{ openapply_app_start_command }} +AmbientCapabilities=CAP_NET_BIND_SERVICE +CapabilityBoundingSet=CAP_NET_BIND_SERVICE Restart=on-failure RestartSec=3