UpdraftPlus and similar plugins work fine. But if you want full control and want to avoid yet another plugin dependency, there's an alternative that requires half an hour of setup and then takes care of itself.
The concept
A bash script running via cron. It dumps the database with mysqldump, creates a compressed archive of wp-content, and syncs to an external storage location with rclone. The whole script is maybe 25 lines.
The database dump
mysqldump -u user -p'password' dbname | gzip > /backups/db_$(date +%Y%m%d).sql.gz
Takes seconds for a normal WordPress database. Compressed, it rarely weighs more than a few megabytes.
The files
tar czf /backups/wp-content_$(date +%Y%m%d).tar.gz /var/www/html/wp-content/
Takes longer if you have lots of media, but it runs at night so it doesn't matter.
Offsite with rclone
Rclone supports 40+ cloud services. Google Drive, Amazon S3, Backblaze B2, SFTP, Hetzner Storage Box. Configure once with rclone config. Then rclone copy /backups remote:wordpress-backups is all you need.
Backblaze B2 costs 0.005 USD per GB per month. Backup doesn't get cheaper than that.
Rotation
Keep 7 daily, 4 weekly, 12 monthly. find /backups -name "*.gz" -mtime +7 -delete cleans old dailies. Add logic for weekly and monthly backups. Schedule with crontab -e.
Test the restore process at least once. A backup you can't restore isn't a backup.