digraph static {
        label="static site mirror system architecture, torproject.org, november 2020"
        node [shape=record]
        subgraph "clusterhosts" {
                label="hosts"
                labelloc=bottom

                source [ label="<host> source | <update> static-update-component"]
                master [ label="<host> master | { <update> static-master-update-component | <run> static-master-run }" ]
                mirror [ label="<host> mirror | { <run> static-mirror-run }" ]
                source:update -> master:update [taillabel="runs"]
                master:update -> source:host [label="rsync from"]
                master:update -> master:run [label="runs"]
                master:run -> mirror:run [taillabel="runs"]
                mirror:run -> master:host [label="rsync from"]
                note [shape="note" label="note:\nthere can be many\n source, master\nand mirror hosts"]
                git:gitolite -> jenkins [label="trigger"]
                jenkins -> git:git [label="pull"]
                jenkins -> source:host [taillabel="push"]
                git [ label="<gitolite> gitolite | <git> git://" ]
                puppet
                dns [ label="DNS server | { <bind> zonefiles | <nag> mininag }" ]
                dns:nag -> mirror:host [label="monitors"]
                dns:nag -> dns:bind [ label="updates"]
        }
        subgraph "clusterusers" {
                label="users"
                labelloc=bottom
                TPA
                webdevs
                public
        }
        TPA -> puppet -> { source:host, master:host, mirror:host, git }
        TPA -> { git:gitolite, jenkins }
        webdevs -> source:host [ label="rsync" ]
        webdevs -> source:update [ label="sudo" ]
        webdevs -> git
        public -> { mirror:host, dns } [ label="browses" ]
}
