Enable boot startup for Atlas iCloudPD

This commit is contained in:
Fabio Scotto di Santolo
2026-10-03 13:59:05 +02:00
parent 755f24bc72
commit 2dfe766b7b
5 changed files with 51 additions and 13 deletions

View File

@@ -61,7 +61,7 @@ Ansible-driven personal infrastructure repo for Fedora and Void desktops, Fedora
`ansible-playbook ansible/site.yml --limit atlas --tags storage,sharing,containers --check --diff`
- Atlas rootless Gitea staging (does not start Gitea):
`ansible-playbook ansible/site.yml --limit atlas --tags gitea --check --diff`
- Atlas iCloudPD storage and inactive Quadlet (does not start it):
- Atlas iCloudPD storage and boot-started Quadlet:
`ansible-playbook ansible/site.yml --limit atlas --tags icloudpd --check --diff`
- Atlas explicit Gitea host-owner migration (live outage; never a normal run):
`ansible-playbook ansible/site.yml --limit atlas --tags gitea_owner_migration -e atlas_gitea_owner_migration=true`
@@ -375,8 +375,10 @@ successfully. The first monthly scrub remains a runtime check.
- [x] Deploy the declared Atlas iCloudPD state dataset and inactive rootless `admin` Quadlet.
Photos belong under `/zpool/archive/Pictures/iCloudPD`; private config/MFA state belongs in
`zpool/services/data/icloudpd`. Photobook remains reserved for Immich. Ansible now renders
`icloudpd.conf` with the Apple ID from the existing Vault key, but does not store the password,
manage MFA, or enable automatic startup. The isolated no-network layout test is documented in
`icloudpd.conf` with the Apple ID from the existing Vault key, but does not store the password
or manage MFA. Automatic startup was approved on 2026-10-03; the Quadlet now
uses `WantedBy=default.target` and Ansible keeps the service running.
The isolated no-network layout test is documented in
`docs/atlas-icloudpd-migration.md`. On 2026-10-02 Atlas deployment and a second idempotent run
passed; no app config existed at deployment. A manual first start on 2026-10-02 generated
`icloudpd.conf`; an Ansible run then replaced it with a private mode-0600 Vault-backed template

View File

@@ -13,7 +13,7 @@
- atlas_icloudpd_image is search('@sha256:[0-9a-f]{64}$')
fail_msg: Verify the fixed, separate Atlas iCloudPD photo and state paths.
- name: Declare inactive rootless Atlas iCloudPD storage and Quadlet
- name: Declare rootless Atlas iCloudPD storage and boot-started Quadlet
tags: [atlas, icloudpd]
block:
- name: Inspect the existing Archive and application-data datasets
@@ -162,4 +162,27 @@
owner: "{{ atlas_admin_username }}"
group: "{{ atlas_admin_group }}"
mode: "0644"
notify: Reload Atlas admin user manager
register: atlas_icloudpd_quadlet
- name: Reload the Atlas admin user manager after iCloudPD Quadlet changes
become_user: "{{ atlas_admin_username }}"
ansible.builtin.systemd:
scope: user
daemon_reload: true
environment:
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_admin_uid }}/bus"
when:
- atlas_icloudpd_quadlet.changed
- not ansible_check_mode
- name: Keep the rootless Atlas iCloudPD service running
become_user: "{{ atlas_admin_username }}"
ansible.builtin.systemd:
name: atlas-icloudpd.service
scope: user
state: started
environment:
XDG_RUNTIME_DIR: "/run/user/{{ atlas_admin_uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ atlas_admin_uid }}/bus"
when: not ansible_check_mode

View File

@@ -20,7 +20,7 @@
- name: Import staged Atlas rootless Gitea tasks
ansible.builtin.import_tasks: gitea.yml
- name: Import Atlas iCloudPD storage and inactive Quadlet tasks
- name: Import Atlas iCloudPD storage and boot-started Quadlet tasks
ansible.builtin.import_tasks: icloudpd.yml
- name: Import explicit Atlas Gitea restore rehearsal tasks

View File

@@ -1,4 +1,4 @@
# Managed by Ansible. No install target or automatic start.
# Managed by Ansible. Start automatically with the lingering admin user manager.
[Unit]
Description=Atlas rootless iCloud Photos Downloader
RequiresMountsFor={{ atlas_icloudpd_state_dir }} {{ atlas_icloudpd_photos_dir }}
@@ -20,3 +20,6 @@ NoNewPrivileges=true
Restart=on-failure
RestartSec=300
TimeoutStartSec=900
[Install]
WantedBy=default.target

View File

@@ -55,11 +55,12 @@ path, user/UID, and folder format as the bind mounts. References:
The photo subtree receives a managed marker and the image's `.mounted` file.
An existing unmarked path is refused rather than taken over. The existing
Pictures tree is not chowned or emptied. The Quadlet has no `[Install]`
section, so Ansible does not start or enable it. Ansible renders a mode-0600
Pictures tree is not chowned or emptied. The Quadlet now has `[Install]` with
`WantedBy=default.target`, so the lingering admin user manager starts it at boot.
Ansible keeps the service running. Ansible renders a mode-0600
`icloudpd.conf` with `no_log` and no diff, but does not pull the image,
initialize MFA, or run a cutover task. The service was started manually and
will not start automatically after reboot under this design.
initialize MFA, or run a cutover task. Boot startup was approved on 2026-10-03
after a reboot left the previously manual-started service inactive.
The previous gated check-mode tests and isolated Quadlet-generator test proved
only the proposed layout; they predate the simplified declarative role. They
@@ -110,8 +111,8 @@ completed backup or restore of iCloudPD data**, which did not exist at the time.
on first start. Ansible replaced that default file with a private template
using the Apple ID already in Vault. The operator initialized password
and MFA interactively; never put credentials or codes in the repository,
chat, or Ansible extra-vars. The Quadlet has no automatic boot start;
enablement requires a separate deliberate design change.
chat, or Ansible extra-vars. Automatic boot startup was separately approved
on 2026-10-03; this does not change the interactive MFA procedure.
- Initial ingestion completed on 2026-10-03. Still check folder structure,
ownership, SELinux and SMB access, no unintended deletions, the next daily
cycle, completed Borg and USB versions, and isolated restore of photos and
@@ -161,3 +162,12 @@ is a filesystem file count, not a count of distinct iCloud assets. A later
read-only check found the service still active. This closes initial
authentication and ingestion only: a subsequent daily cycle and end-to-end
recovery of the new photos and private state remain untested.
On 2026-10-03 Atlas rebooted at 10:17 CEST; iCloudPD stayed inactive because
its Quadlet had no install target. A manual start restored the running service
and the application began listing iCloud files. The operator then approved
persistent boot startup. The managed Quadlet now declares
`WantedBy=default.target`; the live generator created
`default.target.wants/atlas-icloudpd.service`, admin has `Linger=yes`, and the
service remained active with zero restarts. No NAS reboot was performed to
test this change; actual post-reboot startup remains untested.