--- - name: Install Docker SDK for Python apt: name: python3-docker state: present become: true - name: Download latest docker-compose from GitHub shell: | curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose become: true - name: Verify docker-compose installation shell: /usr/local/bin/docker-compose --version register: compose_version become: true - name: Show docker-compose version debug: msg: "{{ compose_version.stdout }}" - name: Create paperclip directories file: path: "{{ item }}" state: directory mode: '0755' owner: root group: root loop: - "{{ paperclip_base_path }}" - "{{ paperclip_data_dir }}" - "{{ paperclip_certs_dir }}" - "{{ paperclip_base_path }}/pgdata" become: true - name: Create OpenCode config directory file: path: "{{ paperclip_base_path }}/.config/opencode" state: directory mode: '0755' owner: 1000 group: 1000 become: true - name: Create OpenCode .local/share directory file: path: "{{ paperclip_base_path }}/.local/share/opencode" state: directory mode: '0755' owner: 1000 group: 1000 become: yes - 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 - name: Fix directory ownership for container user (UID 1000) shell: | chown -R 1000:1000 {{ paperclip_data_dir }} chown -R 1000:1000 {{ paperclip_base_path }}/pgdata chown -R 1000:1000 {{ paperclip_base_path }}/.config become: true - name: Write secrets and configuration to .env copy: content: | # Authentication secrets (from vault) BETTER_AUTH_SECRET={{ vault_better_auth_secret }} PAPERCLIP_AGENT_JWT_SECRET={{ vault_paperclip_agent_jwt_secret }} # Infrastructure configuration CLOUDFLARE_API_TOKEN={{ vault_cloudflare_api_token }} CERTBOT_EMAIL={{ certbot_email }} PAPERCLIP_DOMAIN={{ paperclip_domain }} VLLM_ENDPOINT={{ vllm_endpoint }} VLLM_API_KEY={{ vault_vllm_api_key }} dest: "{{ paperclip_base_path }}/.env" mode: '0600' owner: root group: root become: true no_log: true - name: Template docker-compose.yml template: src: docker-compose.yml.j2 dest: "{{ paperclip_base_path }}/docker-compose.yml" mode: '0644' owner: root group: root become: true notify: Restart paperclip stack - name: Template nginx config template: src: nginx.conf.j2 dest: "{{ paperclip_base_path }}/nginx.conf" mode: '0644' owner: root group: root become: true notify: Reload nginx - name: Template certbot init script template: src: certbot-init.sh.j2 dest: "{{ paperclip_base_path }}/certbot-init.sh" mode: '0755' owner: root group: root become: true - name: Template OpenCode config 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 - name: Stop and remove old containers shell: | cd {{ paperclip_base_path }} /usr/local/bin/docker-compose down --remove-orphans 2>/dev/null || true become: true ignore_errors: true - name: Deploy docker compose stack shell: | cd {{ paperclip_base_path }} /usr/local/bin/docker-compose up -d become: true register: compose_result - name: Wait for Paperclip to be ready uri: url: "http://localhost:{{ paperclip_port }}/health" status_code: 200 register: result until: result.status == 200 retries: 30 delay: 5 ignore_errors: true - name: Wait for nginx to be ready uri: url: "https://{{ paperclip_domain }}/" validate_certs: no status_code: [200, 301, 302] register: result until: result.status in [200, 301, 302] retries: 30 delay: 5 ignore_errors: true - name: Verify Paperclip is accessible via https debug: msg: "Paperclip is accessible at https://{{ paperclip_domain }}" when: result.status is defined and result.status in [200, 301, 302]