Migrate devpi from minikube to indri (launchd) #341
6 changed files with 148 additions and 1 deletions
infra: devpi role for launchd on indri, retire from minikube
- New ansible role ansible/roles/devpi installs devpi-server + devpi-web into a uv-managed venv at ~erichblume/devpi/venv, initializes the server-dir on first run (via 1Password root password fetched in playbook pre_tasks), and runs as a LaunchAgent bound to 127.0.0.1:3141. - Caddy: switch the pypi.ops.eblu.me backend from the tailscale ingress to http://localhost:3141. - Playbook indri.yml: add pre_tasks to fetch the devpi root password from 1Password and include the new role. The minikube StatefulSet has been scaled to 0 to free memory; the ArgoCD app + manifests will be removed in a follow-up commit once the launchd service is verified. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
commit
a64797b86f
|
|
@ -212,6 +212,23 @@
|
|||
no_log: true
|
||||
tags: [forgejo_metrics]
|
||||
|
||||
# Devpi root password (PyPI mirror admin)
|
||||
- name: Fetch devpi root password
|
||||
ansible.builtin.command:
|
||||
cmd: op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/kyhzfifryqnuk7jeyibmmjvxxm/add more/root password"
|
||||
delegate_to: localhost
|
||||
register: _devpi_root_password
|
||||
changed_when: false
|
||||
no_log: true
|
||||
check_mode: false
|
||||
tags: [devpi]
|
||||
|
||||
- name: Set devpi root password fact
|
||||
ansible.builtin.set_fact:
|
||||
devpi_root_password: "{{ _devpi_root_password.stdout }}"
|
||||
no_log: true
|
||||
tags: [devpi]
|
||||
|
||||
roles:
|
||||
- role: alloy
|
||||
tags: alloy
|
||||
|
|
@ -227,6 +244,8 @@
|
|||
tags: zot
|
||||
- role: zot_metrics
|
||||
tags: zot_metrics
|
||||
- role: devpi
|
||||
tags: devpi
|
||||
- role: minikube
|
||||
tags: minikube
|
||||
- role: minikube_metrics
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ caddy_services:
|
|||
backend: "https://feed.tail8d86e.ts.net"
|
||||
- name: devpi
|
||||
host: "pypi.{{ caddy_domain }}"
|
||||
backend: "https://pypi.tail8d86e.ts.net"
|
||||
backend: "http://localhost:3141"
|
||||
- name: kiwix
|
||||
host: "kiwix.{{ caddy_domain }}"
|
||||
backend: "https://kiwix.tail8d86e.ts.net"
|
||||
|
|
|
|||
21
ansible/roles/devpi/defaults/main.yml
Normal file
21
ansible/roles/devpi/defaults/main.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
# devpi PyPI caching mirror (native launchd, replaces minikube StatefulSet)
|
||||
|
||||
devpi_home: /Users/erichblume/devpi
|
||||
devpi_venv: "{{ devpi_home }}/venv"
|
||||
devpi_server_dir: "{{ devpi_home }}/server-dir"
|
||||
devpi_binary: "{{ devpi_venv }}/bin/devpi-server"
|
||||
devpi_init_binary: "{{ devpi_venv }}/bin/devpi-init"
|
||||
|
||||
devpi_python_version: "3.12"
|
||||
devpi_server_version: "6.19.3"
|
||||
devpi_web_version: "5.0.2"
|
||||
|
||||
devpi_host: 127.0.0.1
|
||||
devpi_port: 3141
|
||||
devpi_outside_url: "https://pypi.ops.eblu.me"
|
||||
|
||||
devpi_log_dir: /Users/erichblume/Library/Logs
|
||||
|
||||
# uv binary on indri — mise shim so version bumps via `mise upgrade uv` flow through transparently
|
||||
devpi_uv_binary: /Users/erichblume/.local/share/mise/shims/uv
|
||||
6
ansible/roles/devpi/handlers/main.yml
Normal file
6
ansible/roles/devpi/handlers/main.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: Restart devpi
|
||||
ansible.builtin.shell: |
|
||||
launchctl unload ~/Library/LaunchAgents/mcquack.eblume.devpi.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/mcquack.eblume.devpi.plist
|
||||
changed_when: true
|
||||
67
ansible/roles/devpi/tasks/main.yml
Normal file
67
ansible/roles/devpi/tasks/main.yml
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
# devpi role — devpi-server in a uv-managed venv, run via LaunchAgent.
|
||||
# Replaces the prior minikube StatefulSet; see [[devpi-on-indri]].
|
||||
#
|
||||
# The root password is fetched in the indri.yml playbook pre_tasks and
|
||||
# exposed as `devpi_root_password`.
|
||||
|
||||
- name: Ensure devpi home exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ devpi_home }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure devpi server-dir exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ devpi_server_dir }}"
|
||||
state: directory
|
||||
mode: '0700'
|
||||
|
||||
- name: Create devpi venv if missing
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ devpi_uv_binary }} venv --python {{ devpi_python_version }} {{ devpi_venv }}"
|
||||
creates: "{{ devpi_venv }}/bin/python"
|
||||
|
||||
- name: Install devpi-server and devpi-web into venv
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
{{ devpi_uv_binary }} pip install
|
||||
--python {{ devpi_venv }}/bin/python
|
||||
devpi-server=={{ devpi_server_version }}
|
||||
devpi-web=={{ devpi_web_version }}
|
||||
register: devpi_pip_install
|
||||
changed_when: "'Installed' in devpi_pip_install.stdout or 'Uninstalled' in devpi_pip_install.stdout"
|
||||
notify: Restart devpi
|
||||
|
||||
- name: Check if devpi server-dir is initialized
|
||||
ansible.builtin.stat:
|
||||
path: "{{ devpi_server_dir }}/.serverversion"
|
||||
register: devpi_serverversion
|
||||
|
||||
- name: Initialize devpi server-dir
|
||||
ansible.builtin.command:
|
||||
cmd: >-
|
||||
{{ devpi_init_binary }}
|
||||
--serverdir {{ devpi_server_dir }}
|
||||
--root-passwd {{ devpi_root_password }}
|
||||
when: not devpi_serverversion.stat.exists
|
||||
no_log: true
|
||||
|
||||
- name: Deploy devpi LaunchAgent plist
|
||||
ansible.builtin.template:
|
||||
src: devpi.plist.j2
|
||||
dest: ~/Library/LaunchAgents/mcquack.eblume.devpi.plist
|
||||
mode: '0644'
|
||||
notify: Restart devpi
|
||||
|
||||
- name: Check if devpi LaunchAgent is loaded
|
||||
ansible.builtin.command: launchctl list mcquack.eblume.devpi
|
||||
register: devpi_launchctl_check
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Load devpi LaunchAgent if not loaded
|
||||
ansible.builtin.command: launchctl load ~/Library/LaunchAgents/mcquack.eblume.devpi.plist
|
||||
when: devpi_launchctl_check.rc != 0
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
34
ansible/roles/devpi/templates/devpi.plist.j2
Normal file
34
ansible/roles/devpi/templates/devpi.plist.j2
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- {{ ansible_managed }} -->
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>mcquack.eblume.devpi</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>{{ devpi_binary }}</string>
|
||||
<string>--serverdir</string>
|
||||
<string>{{ devpi_server_dir }}</string>
|
||||
<string>--host</string>
|
||||
<string>{{ devpi_host }}</string>
|
||||
<string>--port</string>
|
||||
<string>{{ devpi_port }}</string>
|
||||
<string>--outside-url</string>
|
||||
<string>{{ devpi_outside_url }}</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>{{ devpi_venv }}/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
||||
</dict>
|
||||
<key>StandardOutPath</key>
|
||||
<string>{{ devpi_log_dir }}/mcquack.devpi.out.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>{{ devpi_log_dir }}/mcquack.devpi.err.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
Loading…
Add table
Add a link
Reference in a new issue