Software does not end at git push.
A feature is not finished until someone else can install it, recover it from a bad day and find out when it breaks.

Containers as the unit of delivery
Each of my products ships as a Docker Compose stack: a database, an API and a web service. Rechvix, OrderRestro and KinetiRx are also packaged for CasaOS. Packaging for a store taught me things a laptop never does, such as a bind-mounted directory that starts empty because there is no repository on the target machine.
CI/CD
Projects build and test on every pull request, and sites deploy from a push to main through a self-hosted runner that builds an image and replaces the running container. Rechvix's pipeline also runs Go static checks, a frontend job, a Docker build and an accessibility suite.
Reverse proxies and exposure
Nginx fronts Submify and KinetiRx so the browser sees a single origin. I also use tunnels for services behind a home or office connection, which brings its own details, for example the Secure-cookie behaviour described in Offline-first restaurant software.
Backups and recovery
A backup that has never been restored is a hope. For Rechvix I wrote a restore drill: restore into a scratch PostgreSQL, then verify row counts and that the trial balance still balances. KinetiRx keeps a rolling backup for its reset tool.
Observability and reliability
I monitor what a user would notice first: is the service up, is the disk filling, did the last deploy change behaviour. Dashboards, logs and error tracking are part of a project's definition of done. I keep notes on the mistakes, such as a container that ignored its updated environment file.
My own infrastructure
I run a Proxmox and TrueNAS environment for my own services and testing.