en

Automating Tor Relay Deployment with Ansible

Operating multiple Tor relays manually becomes unwieldy as the family grows. Ansible provides infrastructure-as-code automation for relay deployment, configuration management, security updates, and monitoring setup. Automating relay management reduces operational overhead, ensures consistent configuration across the family, and enables rapid recovery after server failures. This guide covers practical Ansible automation for Tor relay operations.

Need this done for your project?

We implement, you ship. Async, documented, done in days.

Start a Brief

Ansible Inventory Structure for Relay Families

Structure your Ansible inventory to reflect the relay family organization. Create an inventory/hosts.yml with groups: tor_relays (all relay hosts), tor_guards (guard-eligible relays), tor_exits (exit relays), tor_bridges (bridge relays). Each host entry includes ansible_host (IP), ansible_user (deploy user), ansible_ssh_private_key_file (key path), and relay-specific variables (tor_nickname, tor_bandwidth_rate, tor_bandwidth_burst). Group variables in inventory/group_vars/tor_relays.yml define common configuration (tor_exit_policy, log settings, contact info). Host variables in inventory/host_vars/.yml define per-relay specifics. This structure allows you to apply playbooks to the entire family or specific subgroups.

Tor Installation Playbook

Create roles/tor/tasks/main.yml for relay installation. Add the Tor Project's apt repository and GPG key using ansible.builtin.apt_key and ansible.builtin.apt_repository. Install packages: tor, tor-geoipdb, nyx, prometheus-node-exporter. Deploy the torrc template from templates/torrc.j2 using ansible.builtin.template. The torrc template uses Jinja2 variables for per-relay configuration: {{ tor_nickname }}, {{ tor_bandwidth_rate }}, {{ tor_orport }}, {{ tor_contact_info }}. The MyFamily line is generated from a group variable listing all relay fingerprints: MyFamily {{ tor_family_fingerprints | join(',') }}. After torrc deployment, run handlers: restart tor and verify Tor bootstraps to 100% using a wait_for task checking the notices log.

Automated MyFamily Management

The hardest part of family management automation is keeping MyFamily current as relays are added or removed. Implement a dynamic inventory plugin that queries Onionoo API (onionoo.torproject.org/details) for current relay fingerprints by ContactInfo. When a new relay is deployed and added to Onionoo (typically 3-4 hours after launch), re-run the playbook on all existing relays to update their MyFamily with the new fingerprint. For the new relay, retrieve its fingerprint from /var/lib/tor/fingerprint and add it to the inventory. Ansible's fetch module retrieves fingerprint files from all relay hosts. A custom Python lookup plugin combines fetched fingerprints into the MyFamily string.

Update Management and Security Patching

Automate security updates across the relay family. Create a playbook that runs ansible.builtin.apt with upgrade: security and update_cache: yes. Schedule via cron or Ansible AWX/Tower. For Tor-specific updates, use a dedicated task that checks the installed Tor version against the latest release version from the Tor Project's apt repository. When updates are available: drain circuits gracefully (send SIGNAL DORMANT via control port, wait 5 minutes for circuits to clear), apply updates, restart Tor, verify successful bootstrap. Stagger update timing across the relay family (add per-host delay using inventory variables) to avoid simultaneously taking multiple relays offline during update windows.

Monitoring Deployment via Ansible

Deploy Prometheus node_exporter and Tor control port metrics exporters using Ansible. The role installs prometheus-node-exporter (available in standard repos), configures it to listen on 127.0.0.1:9100, and creates a firewall rule allowing Prometheus server to scrape. For Tor metrics, deploy the tor-exporter Python package and configure it to query the Tor control port. Deploy Alertmanager configuration from templates with relay family-specific alert routing. After deployment, the Prometheus scrape targets inventory (prometheus/targets.yml) is regenerated from Ansible inventory using a template that lists all relay host:port combinations. Run the monitoring deployment playbook whenever the relay family membership changes.

Why Anubiz Host

100% async — no calls, no meetings
Delivered in days, not weeks
Full documentation included
Production-grade from day one
Security-first approach
Post-delivery support included

Ready to get started?

Skip the research. Tell us what you need, and we'll scope it, implement it, and hand it back — fully documented and production-ready.

Anubiz Chat AI

Online