litellm: add OpenAI→Meridian shim role (venv + systemd, port 4000)
LiteLLM sits in front of Meridian for clients that can't talk Anthropic's /v1/messages format (Pulse OpenAI provider, paperless-ai, etc.). Routes OpenAI-shaped requests to localhost:3456 (Meridian) which forwards to the Max sub. - New roles/litellm/ — Python venv, pip install litellm[proxy], systemd - vars/main.yml — model map (haiku/sonnet/opus) + LITELLM_MASTER_KEY env lookup - site.yml — adds litellm role + sanity-check assert - deploy.sh — pulls LITELLM_MASTER_KEY from Infisical (/meridian/) on the controller and exports it for the playbook - New Infisical secret /meridian/vault_litellm_master_key Smoke: Pulse → LiteLLM /v1/chat/completions → Meridian /v1/messages → Max sub returns "pong" through both the LiteLLM master key auth and the Claude Code SDK OAuth. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
---
|
||||
# LiteLLM — OpenAI-compatible proxy that fronts Meridian's Anthropic
|
||||
# /v1/messages endpoint. Lets Anthropic-unfriendly clients (Pulse's
|
||||
# OpenAI provider, paperless-ai, etc.) talk to the Max sub via Meridian.
|
||||
|
||||
- name: Ensure python3-venv is installed (LiteLLM runs in a venv)
|
||||
apt:
|
||||
name:
|
||||
- python3-venv
|
||||
- python3-pip
|
||||
state: present
|
||||
|
||||
- name: Ensure litellm system user
|
||||
user:
|
||||
name: "{{ litellm_user }}"
|
||||
system: true
|
||||
home: "{{ litellm_home }}"
|
||||
shell: /usr/sbin/nologin
|
||||
create_home: true
|
||||
state: present
|
||||
|
||||
- name: Ensure litellm home perms
|
||||
file:
|
||||
path: "{{ litellm_home }}"
|
||||
state: directory
|
||||
owner: "{{ litellm_user }}"
|
||||
group: "{{ litellm_user }}"
|
||||
mode: '0755'
|
||||
|
||||
# Pip install runs as root (LXC filesystem doesn't support the ACL flip
|
||||
# Ansible uses for become_user). Venv contents end up root-owned, which is
|
||||
# fine — systemd runs the proxy as the litellm user and only needs read+exec.
|
||||
|
||||
- name: Create litellm venv
|
||||
command: python3 -m venv {{ litellm_venv }}
|
||||
args:
|
||||
creates: "{{ litellm_venv }}/bin/python"
|
||||
|
||||
- name: Upgrade pip + wheel + setuptools in venv
|
||||
pip:
|
||||
name:
|
||||
- pip
|
||||
- wheel
|
||||
- setuptools
|
||||
state: latest
|
||||
virtualenv: "{{ litellm_venv }}"
|
||||
virtualenv_command: python3 -m venv
|
||||
|
||||
- name: Install LiteLLM into venv
|
||||
pip:
|
||||
name: "{{ litellm_package_spec }}"
|
||||
virtualenv: "{{ litellm_venv }}"
|
||||
virtualenv_command: python3 -m venv
|
||||
notify: restart litellm
|
||||
|
||||
- name: Resolve litellm binary
|
||||
stat:
|
||||
path: "{{ litellm_venv }}/bin/litellm"
|
||||
register: litellm_bin
|
||||
|
||||
- name: Fail if litellm binary missing
|
||||
fail:
|
||||
msg: "litellm not installed at {{ litellm_venv }}/bin/litellm"
|
||||
when: not litellm_bin.stat.exists
|
||||
|
||||
- name: Drop LiteLLM config
|
||||
template:
|
||||
src: litellm-config.yaml.j2
|
||||
dest: "{{ litellm_home }}/config.yaml"
|
||||
owner: "{{ litellm_user }}"
|
||||
group: "{{ litellm_user }}"
|
||||
mode: '0640'
|
||||
notify: restart litellm
|
||||
|
||||
- name: Drop systemd environment file (master key)
|
||||
template:
|
||||
src: litellm.env.j2
|
||||
dest: "{{ litellm_home }}/litellm.env"
|
||||
owner: "{{ litellm_user }}"
|
||||
group: "{{ litellm_user }}"
|
||||
mode: '0600'
|
||||
notify: restart litellm
|
||||
no_log: true
|
||||
|
||||
- name: Deploy litellm systemd unit
|
||||
template:
|
||||
src: litellm.service.j2
|
||||
dest: /etc/systemd/system/litellm.service
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify:
|
||||
- reload systemd
|
||||
- restart litellm
|
||||
|
||||
- name: Flush handlers (reload systemd before enable)
|
||||
meta: flush_handlers
|
||||
|
||||
- name: Enable + start litellm
|
||||
systemd:
|
||||
name: litellm
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
|
||||
- name: Wait for LiteLLM /health
|
||||
uri:
|
||||
url: "http://127.0.0.1:{{ litellm_port }}/health/liveliness"
|
||||
status_code: 200
|
||||
register: litellm_health
|
||||
until: litellm_health.status is defined and litellm_health.status == 200
|
||||
retries: 20
|
||||
delay: 3
|
||||
failed_when: false
|
||||
Reference in New Issue
Block a user