157 lines
5.0 KiB
YAML
157 lines
5.0 KiB
YAML
---
|
|
- name: Create paperclip directories
|
|
ansible.builtin.file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
mode: '0755'
|
|
owner: root
|
|
group: root
|
|
loop:
|
|
- "{{ paperclip_base_path }}"
|
|
# The postgres image chowns its own data dir on start; do not chown it here.
|
|
- "{{ paperclip_base_path }}/pgdata"
|
|
become: true
|
|
tags: [paperclip, files]
|
|
|
|
# Container runs as UID 1000. Deliberately NOT recursive: recurse + mode would
|
|
# chmod every file the app writes under these paths on each run. A fresh
|
|
# deploy has no root-owned content to repair; if you ever need to, run a
|
|
# one-off `chown -R 1000:1000 <dir>` by hand.
|
|
- name: Create container-owned directories (UID 1000)
|
|
ansible.builtin.file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
mode: '0755'
|
|
owner: 1000
|
|
group: 1000
|
|
loop:
|
|
- "{{ paperclip_data_dir }}"
|
|
- "{{ paperclip_base_path }}/.config/opencode"
|
|
- "{{ paperclip_base_path }}/.local/share/opencode"
|
|
become: true
|
|
tags: [paperclip, files]
|
|
|
|
# - name: Deploy OpenCode auth.json with vLLM credentials
|
|
# template:
|
|
# src: opencode-auth.json.j2
|
|
# dest: "{{ paperclip_base_path }}/.local/share/opencode/auth.json"
|
|
# mode: '0600'
|
|
# owner: 1000
|
|
# group: 1000
|
|
# become: true
|
|
# no_log: true
|
|
|
|
# This file is both the compose interpolation source and the container's
|
|
# env_file, so everything here is visible inside the Paperclip container.
|
|
# Infrastructure secrets (Cloudflare token, certbot email) live in
|
|
# /opt/nginx/.env instead.
|
|
- name: Write secrets and configuration to .env
|
|
ansible.builtin.copy:
|
|
content: |
|
|
# Authentication secrets (from vault)
|
|
BETTER_AUTH_SECRET={{ vault_better_auth_secret }}
|
|
PAPERCLIP_AGENT_JWT_SECRET={{ vault_paperclip_agent_jwt_secret }}
|
|
|
|
# Inference endpoints
|
|
ILLUMINATIONS_ENDPOINT={{ illuminations_endpoint }}
|
|
ILLUMINATIONS_API_KEY={{ vault_illuminations_api_key }}
|
|
FANTASMIC_ENDPOINT={{ fantasmic_endpoint }}
|
|
FANTASMIC_API_KEY={{ vault_fantasmic_api_key }}
|
|
dest: "{{ paperclip_base_path }}/.env"
|
|
mode: '0600'
|
|
owner: root
|
|
group: root
|
|
become: true
|
|
no_log: true
|
|
notify: Restart paperclip stack
|
|
tags: [paperclip, files]
|
|
|
|
# No notify: the deploy task below recreates whatever the compose file changed.
|
|
- name: Template docker-compose.yml
|
|
ansible.builtin.template:
|
|
src: docker-compose.yml.j2
|
|
dest: "{{ paperclip_base_path }}/docker-compose.yml"
|
|
mode: '0644'
|
|
owner: root
|
|
group: root
|
|
become: true
|
|
tags: [paperclip, files]
|
|
|
|
# - name: Template OpenCode config
|
|
# ansible.builtin.template:
|
|
# src: opencode.jsonc.j2
|
|
# dest: "{{ paperclip_base_path }}/.config/opencode/opencode.jsonc"
|
|
# mode: '0644'
|
|
# owner: 1000
|
|
# group: 1000
|
|
# become: true
|
|
# notify: Restart paperclip stack
|
|
# tags: [paperclip, files]
|
|
|
|
# Idempotent: only changed services are recreated. remove_orphans also cleans
|
|
# up the old paperclip-nginx / paperclip-certbot containers if they still exist.
|
|
- name: Deploy paperclip stack
|
|
community.docker.docker_compose_v2:
|
|
project_src: "{{ paperclip_base_path }}"
|
|
pull: missing
|
|
remove_orphans: true
|
|
state: present
|
|
register: paperclip_deploy
|
|
become: true
|
|
tags: [paperclip, deploy]
|
|
|
|
- name: Wait for Paperclip to be ready
|
|
ansible.builtin.uri:
|
|
url: "http://localhost:{{ paperclip_port }}/health"
|
|
status_code: 200
|
|
register: paperclip_health
|
|
until: paperclip_health.status == 200
|
|
retries: 30
|
|
delay: 5
|
|
ignore_errors: true
|
|
tags: [paperclip, deploy, verify]
|
|
|
|
- name: Warn if Paperclip never became healthy
|
|
ansible.builtin.debug:
|
|
msg: "WARNING: Paperclip did not report healthy on port {{ paperclip_port }}. Check: docker logs paperclip"
|
|
when: paperclip_health.status | default(0) != 200
|
|
tags: [paperclip, verify]
|
|
|
|
# Requires day1_deploy_nginx_proxy.yml to have run first.
|
|
- name: Publish Paperclip through nginx-proxy
|
|
ansible.builtin.include_role:
|
|
name: nginx-proxy
|
|
tasks_from: add_vhost
|
|
apply:
|
|
become: true
|
|
tags: [paperclip, nginx]
|
|
vars:
|
|
vhost_name: paperclip
|
|
vhost_domain: "{{ paperclip_domain }}"
|
|
vhost_upstream_port: "{{ paperclip_port }}"
|
|
vhost_health_path: /health
|
|
tags: [paperclip, nginx]
|
|
|
|
# --resolve keeps this independent of DNS: it tests nginx, the cert and the
|
|
# upstream. DNS is a separate (manual) prerequisite.
|
|
- name: Verify HTTPS through nginx
|
|
ansible.builtin.command: >-
|
|
curl -sk -o /dev/null -w '%{http_code}'
|
|
--resolve {{ paperclip_domain }}:443:127.0.0.1
|
|
https://{{ paperclip_domain }}/
|
|
register: paperclip_https
|
|
until: paperclip_https.stdout in ['200', '301', '302']
|
|
retries: 6
|
|
delay: 5
|
|
changed_when: false
|
|
failed_when: false
|
|
tags: [paperclip, verify]
|
|
|
|
- name: Report HTTPS result
|
|
ansible.builtin.debug:
|
|
msg: >-
|
|
{{ 'Paperclip is serving at https://' ~ paperclip_domain
|
|
if paperclip_https.stdout in ['200', '301', '302']
|
|
else 'WARNING: https://' ~ paperclip_domain ~ ' returned ' ~ (paperclip_https.stdout | default('no response')) ~ ' (502 usually means Paperclip is not up yet)' }}
|
|
tags: [paperclip, verify]
|