I'm designing a backup system for several Linux servers on a private NATed network, with a mix of physical machines and virtual machines. I can configure firewall rules, but I'm trying to choose between two architectures.
With a pull model, a dedicated backup server initiates connections to each client and retrieves the data using tools such as Borg, Restic, Bareos, or rsnapshot. This centralizes scheduling, policy enforcement, monitoring, and reporting, but requires some form of inbound access to the clients.
With a push model, each client initiates its own backup and sends data to the backup server. This works more naturally through NAT and usually requires only outbound client connections, but it distributes credentials and scheduling logic. I'm also concerned that a compromised client might delete or encrypt its own backups, overwrite another client's data, or quietly stop sending backups.
The goal is to have encrypted, versioned, preferably immutable backups with a small attack surface. I'd like practical advice on pull versus push, authentication methods such as SSH keys, TLS, or API tokens, and ways to secure either design. I'm also interested in hybrid approaches where a central server triggers a client-side backup, as well as lessons learned involving ransomware, silent failures, restores, permissions, and bare-metal recovery. My current approach is rsnapshot running on the hosts, followed by synchronization to backup storage.
5 Answers
Some enterprise tools combine the advantages of both designs. For example, the central director can schedule and authorize a job, while the client makes an outbound connection to the storage service and sends the data. The client cannot independently create arbitrary jobs or purge volumes, and backup volumes are written separately rather than overwritten. This is useful in NATed environments because clients generally only need outbound firewall access.
Whichever direction you choose, visibility and recovery testing matter more than the architecture label. Centralize reporting, alert when a host misses its schedule, verify checksums, test database restores, and periodically perform complete recovery exercises. Use encryption with keys stored separately from the clients, restrict credentials to the minimum required operations, and maintain multiple copies with at least one isolated from the normal network.
Push can be made reasonably safe if the repository is designed for it. Give every client its own repository or namespace, use separate credentials, and restrict those credentials to append-only access with no ability to delete or expire snapshots. Borg append-only repositories and similar immutable storage features are useful here. The backup system itself should be the only component allowed to prune old data or perform maintenance.
A pull model is often preferred when ransomware resistance is the main concern. A dedicated backup host can connect to the systems, while the source machines have no credentials or write access to the backup repository. Keep that host isolated, restrict its firewall access, use narrowly scoped SSH keys or service accounts, and monitor every backup job. The tradeoff is that the backup server becomes a highly valuable target, so it needs strong isolation and hardening.
The important part is not just pull versus push. Keep an additional copy offline or otherwise air-gapped, rotate it, and regularly verify that restores actually work.
There is no universal winner because the data layout matters as much as the network direction. For virtual machines, backing up at the hypervisor or storage layer may be simplest. Physical systems may need a client-side tool to correctly handle permissions, extended attributes, mount points, databases, and bare-metal recovery. It can be sensible to combine approaches: client-side application-consistent backups, host or hypervisor snapshots, and a separate backup server that validates, replicates, and checks the results.
That makes sense. I’m leaning toward keeping the host-side rsnapshot jobs for the physical systems, then having a separate, isolated system synchronize and verify the resulting backup sets.

That protects older snapshots, but storage exhaustion is still possible. Set per-client quotas, alert on unusual growth, and monitor backup freshness so a broken client cannot fail silently.