> This ripples into absolutely everything - now doing firewall rules is a total pain. Additionally the machines and devices are constantly changing IP addresses (on IPv6).
A dynamic prefix sucks for a number of reasons, but at least for firewall rules you can just match the last 64 bits using a mask. At least, ip6tables can do this.
> Additionally the machines and devices are constantly changing IP addresses
You probably mean the privacy extensions addresses (AKA temporary). Those are complementary to the persistent ones (EUI-64) and shouldn't concern your firewall because they aren't normally used for receiving connections, unless you intend to block outbound traffic.
> I am curious what recommended IPv6 solution is for this classic small biz situations.
For a small business, the recommendation is: get a (static) /48 from your ISP, split it into several /64 subnets, advertise a prefix for each subnet, a DNS server (RDNSS) and let the clients assign their own addresses via SLAAC. There's no need for a DHCPv6 server (in fact some clients don't support it, see Android) or reservations because the addresses are unique and static.
If your ISP is evil and doesn't give you a static prefix, you can advertise a ULA prefix (basically the IPv6 version of RFC 1918) and use that in place of the dynamic one. Clients will use the dynamic prefix for Internet connections and the ULA for local services (printers, NASs, etc.).