My security update system is straightforward but it took quite a lot of thought to get here.
My self hosted things all run as docker containers inside Alpine VMs running on top of Proxmox. Services are defined with Docker Compose. One of those things is a Forgejo git server along with a runner in a separate VM. I have a single command that will deploy everything along with a Forgejo action that invokes that command on a push to main.
I then have Renovate running periodically set to auto-merge patch-level updates and tag updates.
Thus, Renovate keeps me up to date and git keeps everyone honest.