added claude role
This commit is contained in:
1 parent
b1ce761291
commit
7450892a68
13 files changed
+296
-11
No files matched your search
@@ -63,6 +63,14 @@ astro_orbiter:
|
||||
hosts:
|
||||
astro-orbiter:
|
||||
|
||||
claude_servers:
|
||||
hosts:
|
||||
haunted-mansion:
|
||||
ansible_host: 10.1.71.137
|
||||
ansible_user: wed
|
||||
ansible_become: true
|
||||
ansible_ssh_private_key_file: ~/.ssh/ansible
|
||||
|
||||
hermes_server:
|
||||
hosts:
|
||||
carousel-of-progress:
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# install-claude.yml
|
||||
---
|
||||
# Usage: ansible-playbook -i inventory.ini install-claude.yml
|
||||
- name: Install Claude Code on Ubuntu servers
|
||||
hosts: claude_servers
|
||||
become: false # the role escalates only where it needs to
|
||||
roles:
|
||||
- role: claude_code
|
||||
vars:
|
||||
claude_code_install_method: apt # or: native
|
||||
claude_code_apt_channel: stable # or: latest
|
||||
@@ -0,0 +1,35 @@
|
||||
# claude_code role
|
||||
|
||||
Installs [Claude Code](https://code.claude.com/docs/en/setup) on Ubuntu 20.04+ / Debian 10+ (x64 or ARM64, 4 GB+ RAM).
|
||||
|
||||
## Methods
|
||||
|
||||
| `claude_code_install_method` | What it does | Updates |
|
||||
|---|---|---|
|
||||
| `apt` (default) | Adds Anthropic's signed apt repo (stable or latest channel) and installs the `claude-code` package system-wide. Verifies the signing-key fingerprint before trusting it. | `apt upgrade` / set `claude_code_package_state: latest` |
|
||||
| `native` | Runs Anthropic's installer as `claude_code_user`; binary lands in `~/.local/bin/claude`. | Self-updates in the background |
|
||||
|
||||
## Key variables (see `defaults/main.yml`)
|
||||
|
||||
- `claude_code_apt_channel`: `stable` (about a week behind, skips bad releases) or `latest`
|
||||
- `claude_code_package_state`: `present` or `latest`
|
||||
- `claude_code_native_version`: `latest`, `stable`, or a pinned version like `2.1.89`
|
||||
- `claude_code_settings`: optional dict written to `~/.claude/settings.json` (overwrites the file)
|
||||
|
||||
## Use
|
||||
|
||||
```bash
|
||||
cp inventory.ini.example inventory.ini # edit hosts
|
||||
ansible-playbook -i inventory.ini install-claude.yml --check # dry run
|
||||
ansible-playbook -i inventory.ini install-claude.yml
|
||||
```
|
||||
|
||||
The remote user needs sudo for the `apt` method.
|
||||
|
||||
## After install: authenticate (not automated)
|
||||
|
||||
Run `claude` once on the server and follow the login prompt, or export `ANTHROPIC_API_KEY`
|
||||
for the user (store it in Ansible Vault, not in the repo). A Pro, Max, Team, Enterprise or
|
||||
Console account is required; the free claude.ai plan does not include Claude Code.
|
||||
|
||||
Verify with `claude --version` and `claude doctor`.
|
||||
@@ -0,0 +1,39 @@
|
||||
# roles/claude_code/defaults/main.yml
|
||||
---
|
||||
# How to install Claude Code:
|
||||
# apt - signed Anthropic apt repo, system-wide, upgraded via apt (recommended for servers)
|
||||
# native - Anthropic's installer script, per-user in ~/.local/bin, self-updating
|
||||
claude_code_install_method: apt
|
||||
|
||||
# ---- apt method -------------------------------------------------------------
|
||||
# Release channel: "stable" (~1 week behind, skips bad releases) or "latest"
|
||||
claude_code_apt_channel: stable
|
||||
# "present" installs once; "latest" upgrades on every run
|
||||
claude_code_package_state: present
|
||||
|
||||
claude_code_apt_key_url: https://downloads.claude.ai/keys/claude-code.asc
|
||||
claude_code_apt_key_path: /etc/apt/keyrings/claude-code.asc
|
||||
# Fingerprint published in Anthropic's docs; the role refuses to continue if it differs
|
||||
claude_code_apt_key_fingerprint: "31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE"
|
||||
claude_code_apt_repo_base: https://downloads.claude.ai/claude-code/apt
|
||||
|
||||
# ---- native method ----------------------------------------------------------
|
||||
# User the native installer runs as
|
||||
claude_code_user: "{{ ansible_user_id }}"
|
||||
# "latest", "stable", or a specific version such as "2.1.89"
|
||||
claude_code_native_version: latest
|
||||
|
||||
# ---- common -----------------------------------------------------------------
|
||||
claude_code_prereq_packages:
|
||||
- curl
|
||||
- ca-certificates
|
||||
- gnupg
|
||||
|
||||
# Optional: content for ~/.claude/settings.json of claude_code_settings_user.
|
||||
# Empty dict = don't touch the file. NOTE: when set, the file is overwritten.
|
||||
# Example: { "autoUpdatesChannel": "stable", "env": { "DISABLE_AUTOUPDATER": "1" } }
|
||||
claude_code_settings: {}
|
||||
claude_code_settings_user: "{{ claude_code_user }}"
|
||||
|
||||
# Run `claude --version` at the end and fail if it doesn't work
|
||||
claude_code_verify: true
|
||||
@@ -0,0 +1,15 @@
|
||||
# roles/claude_code/meta/main.yml
|
||||
---
|
||||
galaxy_info:
|
||||
role_name: claude_code
|
||||
author: ryan
|
||||
description: Install Claude Code on Ubuntu/Debian servers (signed apt repo or native installer)
|
||||
license: MIT
|
||||
min_ansible_version: "2.14"
|
||||
platforms:
|
||||
- name: Ubuntu
|
||||
versions: [focal, jammy, noble]
|
||||
- name: Debian
|
||||
versions: [buster, bullseye, bookworm]
|
||||
galaxy_tags: [claude, ai, cli]
|
||||
dependencies: []
|
||||
@@ -0,0 +1,70 @@
|
||||
# roles/claude_code/tasks/apt.yml
|
||||
---
|
||||
- name: Create apt keyrings directory
|
||||
ansible.builtin.file:
|
||||
path: /etc/apt/keyrings
|
||||
state: directory
|
||||
mode: "0755"
|
||||
owner: root
|
||||
group: root
|
||||
become: true
|
||||
|
||||
- name: Download Anthropic release signing key
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ claude_code_apt_key_url }}"
|
||||
dest: "{{ claude_code_apt_key_path }}"
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
become: true
|
||||
|
||||
- name: Read key fingerprint
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
set -o pipefail
|
||||
gpg --show-keys --with-colons {{ claude_code_apt_key_path | quote }} | awk -F':' '/^fpr/ {print $10; exit}'
|
||||
executable: /bin/bash
|
||||
register: claude_code_key_fpr
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
become: true
|
||||
|
||||
- name: Refuse to continue if the key fingerprint does not match
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- claude_code_key_fpr.stdout | trim | upper == claude_code_apt_key_fingerprint | upper
|
||||
fail_msg: >-
|
||||
Signing key fingerprint mismatch: got '{{ claude_code_key_fpr.stdout | trim }}',
|
||||
expected '{{ claude_code_apt_key_fingerprint }}'. Removing the key file.
|
||||
quiet: true
|
||||
register: claude_code_key_check
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove untrusted key file
|
||||
ansible.builtin.file:
|
||||
path: "{{ claude_code_apt_key_path }}"
|
||||
state: absent
|
||||
become: true
|
||||
when: claude_code_key_check is failed
|
||||
|
||||
- name: Stop if key check failed
|
||||
ansible.builtin.fail:
|
||||
msg: "{{ claude_code_key_check.msg }}"
|
||||
when: claude_code_key_check is failed
|
||||
|
||||
- name: Configure Claude Code apt repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: >-
|
||||
deb [signed-by={{ claude_code_apt_key_path }}]
|
||||
{{ claude_code_apt_repo_base }}/{{ claude_code_apt_channel }}
|
||||
{{ claude_code_apt_channel }} main
|
||||
filename: claude-code
|
||||
state: present
|
||||
update_cache: true
|
||||
become: true
|
||||
|
||||
- name: Install claude-code package
|
||||
ansible.builtin.apt:
|
||||
name: claude-code
|
||||
state: "{{ claude_code_package_state }}"
|
||||
become: true
|
||||
@@ -0,0 +1,44 @@
|
||||
# roles/claude_code/tasks/main.yml
|
||||
---
|
||||
- name: Assert a supported install method
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- claude_code_install_method in ['apt', 'native']
|
||||
- claude_code_apt_channel in ['stable', 'latest']
|
||||
fail_msg: "claude_code_install_method must be apt|native and claude_code_apt_channel stable|latest"
|
||||
quiet: true
|
||||
|
||||
- name: Assert a supported OS (Ubuntu 20.04+ / Debian 10+)
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_facts['os_family'] == 'Debian'
|
||||
- >-
|
||||
(ansible_facts['distribution'] == 'Ubuntu' and ansible_facts['distribution_version'] is version('20.04', '>='))
|
||||
or (ansible_facts['distribution'] == 'Debian' and ansible_facts['distribution_version'] is version('10', '>='))
|
||||
- ansible_facts['architecture'] in ['x86_64', 'aarch64']
|
||||
fail_msg: "Claude Code needs Ubuntu 20.04+/Debian 10+ on x64 or ARM64"
|
||||
quiet: true
|
||||
|
||||
- name: Install prerequisite packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ claude_code_prereq_packages }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
become: true
|
||||
|
||||
- name: Install via apt repository
|
||||
ansible.builtin.include_tasks: apt.yml
|
||||
when: claude_code_install_method == 'apt'
|
||||
|
||||
- name: Install via native installer
|
||||
ansible.builtin.include_tasks: native.yml
|
||||
when: claude_code_install_method == 'native'
|
||||
|
||||
- name: Write Claude Code settings
|
||||
ansible.builtin.include_tasks: settings.yml
|
||||
when: claude_code_settings | length > 0
|
||||
|
||||
- name: Verify installation
|
||||
ansible.builtin.include_tasks: verify.yml
|
||||
when: claude_code_verify | bool
|
||||
@@ -0,0 +1,20 @@
|
||||
# roles/claude_code/tasks/native.yml
|
||||
---
|
||||
- name: Install Claude Code with the native installer
|
||||
ansible.builtin.shell:
|
||||
cmd: set -o pipefail; curl -fsSL https://claude.ai/install.sh | bash -s {{ claude_code_native_version | quote }}
|
||||
executable: /bin/bash
|
||||
creates: "~{{ claude_code_user }}/.local/bin/claude"
|
||||
become: true
|
||||
become_user: "{{ claude_code_user }}"
|
||||
|
||||
- name: Put ~/.local/bin on PATH for login shells
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/profile.d/claude-code.sh
|
||||
content: |
|
||||
# Managed by Ansible (claude_code role)
|
||||
case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) export PATH="$HOME/.local/bin:$PATH" ;; esac
|
||||
mode: "0644"
|
||||
owner: root
|
||||
group: root
|
||||
become: true
|
||||
@@ -0,0 +1,22 @@
|
||||
# roles/claude_code/tasks/settings.yml
|
||||
---
|
||||
- name: Look up settings user
|
||||
ansible.builtin.getent:
|
||||
database: passwd
|
||||
key: "{{ claude_code_settings_user }}"
|
||||
|
||||
- name: Create ~/.claude directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ ansible_facts['getent_passwd'][claude_code_settings_user][4] }}/.claude"
|
||||
state: directory
|
||||
mode: "0700"
|
||||
owner: "{{ claude_code_settings_user }}"
|
||||
become: true
|
||||
|
||||
- name: Write ~/.claude/settings.json
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ ansible_facts['getent_passwd'][claude_code_settings_user][4] }}/.claude/settings.json"
|
||||
content: "{{ claude_code_settings | to_nice_json }}\n"
|
||||
mode: "0600"
|
||||
owner: "{{ claude_code_settings_user }}"
|
||||
become: true
|
||||
@@ -0,0 +1,17 @@
|
||||
# roles/claude_code/tasks/verify.yml
|
||||
---
|
||||
- name: Check claude --version
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
if command -v claude >/dev/null 2>&1; then claude --version
|
||||
else "$HOME/.local/bin/claude" --version; fi
|
||||
executable: /bin/bash
|
||||
become: "{{ claude_code_install_method == 'native' }}"
|
||||
become_user: "{{ claude_code_user if claude_code_install_method == 'native' else omit }}"
|
||||
register: claude_code_version_out
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
|
||||
- name: Show installed version
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ claude_code_version_out.stdout }}"
|
||||
@@ -1,4 +1,8 @@
|
||||
---
|
||||
# Paperclip Official image
|
||||
paperclip_image: ghcr.io/paperclipai/paperclip
|
||||
paperclip_version: "2026.1001.0" # no "v" prefix; also accepts stable, beta, nightly, canary, sha-<short>
|
||||
|
||||
# Paperclip deployment paths and configuration
|
||||
paperclip_base_path: /opt/paperclip
|
||||
paperclip_data_dir: "{{ paperclip_base_path }}/data"
|
||||
|
||||
@@ -77,16 +77,16 @@
|
||||
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]
|
||||
# - 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.
|
||||
|
||||
@@ -19,7 +19,7 @@ services:
|
||||
retries: 5
|
||||
|
||||
paperclip:
|
||||
image: paperclip-local:latest
|
||||
image: {{ paperclip_image }}:{{ paperclip_version }}
|
||||
container_name: paperclip
|
||||
network_mode: host
|
||||
env_file:
|
||||
|
||||
Reference in new issue
Block a user