personal_infra/ansible/infra/nodito/31_proxmox_community_repos_playbook.yml
counterweight 954b683c71
ansible: delete the duplicated vars files, move globals to group_vars/all
Three files existed only as second copies of things group_vars/all already
auto-loads, and 34 playbooks named them in vars_files: - which outranks
group_vars, so the copies won. The day someone edited one and not the other,
those plays would silently keep the stale value. infra_vars.yml was already
drifting: group_vars/all/main.yml had grown age_backup_recipient and
backup_pull_public_key that it lacked.

  infra_vars.yml          - a strict subset of group_vars/all/main.yml
  infra_secrets.yml       - decrypts byte-identical to group_vars/all/vault.yml
  infra_secrets.yml.example - documented Uptime Kuma credentials as the reason
                              the file exists, which stopped being true

Deleted, along with 62 vars_files entries across 34 playbooks (12 of which
named ../../group_vars/all/main.yml directly - same defect, a vars_files entry
duplicating an auto-loaded file at higher precedence than the file itself).

Checked before touching anything: infra_secrets.yml was listed LAST in 10 plays,
after services_config.yml, so removal would flip precedence if the two shared a
key. They share none, and neither does services_config.yml with
group_vars/all/main.yml, so the removal is provably inert.

services_config.yml was the last one standing. It held four unrelated things:

  caddy_sites_dir            - an identical copy of roles/caddy_site/defaults/.
                               Deleted; the role default is now the only one.
  *.tailscale_hostname (x3)  - a THIRD copy of each box's identity, which
                               inventory.ini already holds as ansible_host.
                               Deleted. Edge plays now read
                               hostvars['<host>'].ansible_host - verified an
                               edge play resolves that with nothing loaded and
                               the other host in no play. Three copies of one
                               name is how bitcoin_rpc_host ended up labelled
                               "knots_box" while pointing at fulcrum-box.
  subdomains, ntfy topic,    - genuinely global: their readers span managed,
  headscale namespace          monitoring, vpn_control and edge, so no single
                               group covers them. Moved to group_vars/all/main.yml
                               where they auto-load. The ntfy_topic and
                               headscale_namespace indirection through
                               service_settings collapses to the global name.
  the four cross-host ports  - the only entries with a real justification.
                               Left in place; they move in the next commit.

Also dead, all Uptime Kuma residue or duplication:
  phoenixd_monitor_name, forgejo_runner healthcheck_timeout_seconds/retries,
  fulcrum_tailscale_hostname, and bitcoin_knots_version - the last being a
  v-prefixed copy of bitcoin_knots_version_short that nothing read, two
  hand-maintained copies of one version string.

Corrected a false comment: services_config.yml claimed the uptime_kuma subdomain
"no longer resolves to anything". It resolves to 164.92.239.72 and answers HTTP
302, and 11 playbooks still template it. Same wrong premise as PLAN_3.

Verification: all 37 playbooks' --list-tasks output is byte-identical before and
after. A probe resolving all 22 values services_config.yml used to supply returns
21 identical and one intended deletion (caddy_sites_dir, now role-only - confirmed
the role still resolves it: "Ensure Caddy sites-enabled directory exists" comes
back ok against the real path). memos check-diff identical before and after.
Syntax passes on every playbook.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-13 20:58:46 +02:00

315 lines
11 KiB
YAML

- name: Switch Proxmox VE from Enterprise to Community Repositories
hosts: hypervisor
become: true
tasks:
- name: Check for deb822 sources format
find:
paths: /etc/apt/sources.list.d/
patterns: "*.sources"
file_type: file
register: deb822_sources
changed_when: false
- name: Check for legacy .list files
find:
paths: /etc/apt/sources.list.d/
patterns: "*.list"
file_type: file
register: legacy_list_files
changed_when: false
- name: Check main sources.list for Proxmox entries
command: grep -q "proxmox\|trixie" /etc/apt/sources.list
register: main_sources_check
failed_when: false
changed_when: false
- name: Display current repository status
debug:
msg: |
Repository status:
- deb822 sources files: {{ deb822_sources.matched }}
- legacy .list files: {{ legacy_list_files.matched }}
- Proxmox/Trixie entries in sources.list: {{ main_sources_check.rc == 0 }}
- name: Check for enterprise repository in deb822 format
shell: |
for file in /etc/apt/sources.list.d/*.sources; do
if grep -q "Components:.*pve-enterprise" "$file" 2>/dev/null; then
echo "$file"
break
fi
done
register: enterprise_deb822_check
failed_when: false
changed_when: false
- name: Check for enterprise repository in legacy format
shell: |
for file in /etc/apt/sources.list.d/*.list; do
if grep -q "enterprise.proxmox.com" "$file" 2>/dev/null; then
echo "$file"
break
fi
done
register: enterprise_legacy_check
failed_when: false
changed_when: false
- name: Check for Ceph enterprise repository in deb822 format
shell: |
for file in /etc/apt/sources.list.d/*.sources; do
if grep -q "enterprise.proxmox.com.*ceph" "$file" 2>/dev/null; then
echo "$file"
break
fi
done
register: ceph_enterprise_deb822_check
failed_when: false
changed_when: false
- name: Check for Ceph enterprise repository in legacy format
shell: |
for file in /etc/apt/sources.list.d/*.list; do
if grep -q "enterprise.proxmox.com.*ceph" "$file" 2>/dev/null; then
echo "$file"
break
fi
done
register: ceph_enterprise_legacy_check
failed_when: false
changed_when: false
- name: Backup enterprise repository files
copy:
src: "{{ item }}"
dest: "{{ item }}.backup"
remote_src: yes
backup: yes
loop: "{{ (enterprise_deb822_check.stdout_lines + enterprise_legacy_check.stdout_lines + ceph_enterprise_deb822_check.stdout_lines + ceph_enterprise_legacy_check.stdout_lines) | select('string') | list }}"
when: (enterprise_deb822_check.stdout_lines + enterprise_legacy_check.stdout_lines + ceph_enterprise_deb822_check.stdout_lines + ceph_enterprise_legacy_check.stdout_lines) | select('string') | list | length > 0
- name: Delete enterprise repository files (deb822 format)
file:
path: "{{ item }}"
state: absent
loop: "{{ enterprise_deb822_check.stdout_lines | select('string') | list }}"
when: enterprise_deb822_check.stdout_lines | select('string') | list | length > 0
- name: Delete enterprise repository files (legacy format)
file:
path: "{{ item }}"
state: absent
loop: "{{ enterprise_legacy_check.stdout_lines | select('string') | list }}"
when: enterprise_legacy_check.stdout_lines | select('string') | list | length > 0
- name: Delete Ceph enterprise repository files (deb822 format)
file:
path: "{{ item }}"
state: absent
loop: "{{ ceph_enterprise_deb822_check.stdout_lines | select('string') | list }}"
when: ceph_enterprise_deb822_check.stdout_lines | select('string') | list | length > 0
- name: Delete Ceph enterprise repository files (legacy format)
file:
path: "{{ item }}"
state: absent
loop: "{{ ceph_enterprise_legacy_check.stdout_lines | select('string') | list }}"
when: ceph_enterprise_legacy_check.stdout_lines | select('string') | list | length > 0
- name: Create community repository file (deb822 format)
copy:
dest: /etc/apt/sources.list.d/proxmox.sources
content: |
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
owner: root
group: root
mode: '0644'
backup: yes
when: deb822_sources.matched > 0
- name: Create community repository file (legacy format)
copy:
dest: /etc/apt/sources.list.d/pve-no-subscription.list
content: |
# PVE pve-no-subscription repository provided by proxmox.com,
# NOT recommended for production use
deb http://download.proxmox.com/debian/pve trixie pve-no-subscription
owner: root
group: root
mode: '0644'
backup: yes
when: deb822_sources.matched == 0
- name: Create Ceph community repository file (deb822 format)
copy:
dest: /etc/apt/sources.list.d/ceph.sources
content: |
Types: deb
URIs: http://download.proxmox.com/debian/ceph-squid
Suites: trixie
Components: no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
owner: root
group: root
mode: '0644'
backup: yes
when: deb822_sources.matched > 0
- name: Create Ceph community repository file (legacy format)
copy:
dest: /etc/apt/sources.list.d/ceph-no-subscription.list
content: |
# Ceph no-subscription repository provided by proxmox.com,
# NOT recommended for production use
deb http://download.proxmox.com/debian/ceph-squid trixie no-subscription
owner: root
group: root
mode: '0644'
backup: yes
when: deb822_sources.matched == 0
- name: Update package cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Verify community repository is working
command: apt-cache policy proxmox-ve
register: community_repo_verify
changed_when: false
- name: Display community repository verification
debug:
var: community_repo_verify.stdout_lines
- name: Update Proxmox packages from community repository
apt:
name: proxmox-ve
state: latest
update_cache: yes
- name: Verify Proxmox VE version
command: pveversion
register: proxmox_version
changed_when: false
- name: Display Proxmox VE version
debug:
msg: "Proxmox VE version: {{ proxmox_version.stdout }}"
- name: Check repository status
shell: apt-cache policy | grep -A 5 -B 5 proxmox
register: final_repo_status
changed_when: false
- name: Display final repository status
debug:
var: final_repo_status.stdout_lines
- name: Verify no enterprise repository warnings
command: apt update
register: apt_update_result
changed_when: false
- name: Check for enterprise repository warnings
fail:
msg: "Enterprise repository warnings detected. Check the output above."
when: "'enterprise.proxmox.com' in apt_update_result.stdout"
- name: Create subscription nag removal script
copy:
dest: /usr/local/bin/pve-remove-nag.sh
content: |
#!/bin/sh
WEB_JS=/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
if [ -s "$WEB_JS" ] && ! grep -q NoMoreNagging "$WEB_JS"; then
echo "Patching Web UI nag..."
sed -i -e "/data\.status/ s/!//" -e "/data\.status/ s/active/NoMoreNagging/" "$WEB_JS"
fi
MOBILE_TPL=/usr/share/pve-yew-mobile-gui/index.html.tpl
MARKER="<!-- MANAGED BLOCK FOR MOBILE NAG -->"
if [ -f "$MOBILE_TPL" ] && ! grep -q "$MARKER" "$MOBILE_TPL"; then
echo "Patching Mobile UI nag..."
printf "%s\n" \
"$MARKER" \
"<script>" \
" function removeSubscriptionElements() {" \
" // --- Remove subscription dialogs ---" \
" const dialogs = document.querySelectorAll('dialog.pwt-outer-dialog');" \
" dialogs.forEach(dialog => {" \
" const text = (dialog.textContent || '').toLowerCase();" \
" if (text.includes('subscription')) {" \
" dialog.remove();" \
" console.log('Removed subscription dialog');" \
" }" \
" });" \
"" \
" // --- Remove subscription cards, but keep Reboot/Shutdown/Console ---" \
" const cards = document.querySelectorAll('.pwt-card.pwt-p-2.pwt-d-flex.pwt-interactive.pwt-justify-content-center');" \
" cards.forEach(card => {" \
" const text = (card.textContent || '').toLowerCase();" \
" const hasButton = card.querySelector('button');" \
" if (!hasButton && text.includes('subscription')) {" \
" card.remove();" \
" console.log('Removed subscription card');" \
" }" \
" });" \
" }" \
"" \
" const observer = new MutationObserver(removeSubscriptionElements);" \
" observer.observe(document.body, { childList: true, subtree: true });" \
" removeSubscriptionElements();" \
" setInterval(removeSubscriptionElements, 300);" \
" setTimeout(() => {observer.disconnect();}, 10000);" \
"</script>" \
"" >> "$MOBILE_TPL"
fi
owner: root
group: root
mode: '0755'
- name: Create APT configuration for nag removal
copy:
dest: /etc/apt/apt.conf.d/no-nag-script
content: |
DPkg::Post-Invoke { "/usr/local/bin/pve-remove-nag.sh"; };
owner: root
group: root
mode: '0644'
- name: Run nag removal script immediately
command: /usr/local/bin/pve-remove-nag.sh
changed_when: false
- name: Reinstall proxmox-widget-toolkit to apply nag removal
apt:
name: proxmox-widget-toolkit
state: present
force: yes
- name: Clean up backup files
file:
path: "{{ item }}"
state: absent
loop:
- /etc/apt/sources.list.d/ceph.sources.backup
- /etc/apt/sources.list.d/pve-enterprise.sources.backup
ignore_errors: yes
- name: Success message
debug:
msg: |
Successfully switched from Proxmox Enterprise to Community repositories.
Enterprise repository has been disabled and community repository is now active.
Subscription nag messages have been disabled.
Proxmox VE version: {{ proxmox_version.stdout }}
IMPORTANT: Clear your browser cache or perform a hard reload (Ctrl+Shift+R)
before using the Proxmox VE Web UI to avoid UI display issues.