diff --git a/howto/ldap.md b/howto/ldap.md
index 4756425a23f3511b93b8f268001aa7a9d1b80d29..1f1319f1e3b4802094b77a758cf4add3e3e373ee 100644
--- a/howto/ldap.md
+++ b/howto/ldap.md
@@ -82,7 +82,7 @@ files under `/var/tmp/bacula-restores`:
  * `/var/tmp/bacula-restores/etc/ldap/slapd.conf`
  * `/var/tmp/bacula-restores/etc/ldap/userdir-ldap-slapd.conf`
 
-They can be copied from `/etc`, with the following modificatiosn:
+They can be copied from `/etc`, with the following modifications:
 
     diff -ru /etc/ldap/slapd.conf etc/ldap/slapd.conf
     --- /etc/ldap/slapd.conf	2011-10-30 15:43:43.000000000 +0000
@@ -165,7 +165,7 @@ are part of the `tordnsel` group, you would call this command:
 In the above, `arlo` and `arma` are members of the `tordnsel` group.
 The fields in the output are in the format of the [group(5)](https://manpages.debian.org/buster/manpages/group.5.en.html) file.
 
-Note that the group membership will vary according to the machie on
+Note that the group membership will vary according to the machine on
 which the command is run, as not all users are present everywhere.
 
 ## Searching LDAP
@@ -223,8 +223,8 @@ object is a `user`, you would need to edit the file in three places:
                SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
 
  3. finally, the new attribute needs to be added to the
-    objectclass. in our example, the field was added alongside the
-    other password fields in the `debianAccount` objectclass, which
+    `objectclass`. in our example, the field was added alongside the
+    other password fields in the `debianAccount` `objectclass`, which
     looked like this after the change:
 
         objectclass ( 1.3.6.1.4.1.9586.100.4.1.1
@@ -262,7 +262,7 @@ case, we had to add the `mailPassword` field to two ACLs:
 
 If those are the only required changes, it is acceptable to directly
 make those changes directly on the LDAP server, as long as the *exact*
-same changes are performed in the git repositoy.
+same changes are performed in the git repository.
 
 It is preferable, however, to [build and
 upload](howto/build_and_upload_debs) `userdir-ldap` as a Debian package instead.
@@ -353,7 +353,7 @@ of all the emails received by the `changes@` alias:
     /srv/db.torproject.org/mail-logs/received.changes
 
 A common problem is people using `--clearsign` instead of `--sign`
-when sending an SSH key. When that hapepns, many email clients
+when sending an SSH key. When that happens, many email clients
 (including Gmail) will word-wrap the SSH key after the comment,
 breaking the signature. For example, this might happen:
 
@@ -373,7 +373,7 @@ breaking the signature. For example, this might happen:
     -----END PGP SIGNATURE-----
 
 Using `--sign --armor` will work around this problem, as the original
-message will all be ascii-armored.
+message will all be ASCII-armored.
 
 ### Dependency loop on new installs
 
@@ -392,7 +392,7 @@ The LDAP server is mostly built by hand and should therefore be
 restored from backups in case of a catastrophic failure. Care should
 be taken to keep the SSH keys of the server intact.
 
-The IP address (and name?) of the LDAP server should not be hardcoded
+The IP address (and name?) of the LDAP server should not be hard-coded
 anywhere. When the server was last renumbered ([issue 33908](https://gitlab.torproject.org/tpo/tpa/team/-/issues/33908)), the
 only changes necessary were on the server itself, in `/etc`. So in
 theory, a fresh new server could be deployed (from backups) in a new
@@ -422,7 +422,7 @@ authentication and authorization, and machines.
 The LDAP setup at Tor is based on the one from Debian.org. It has a
 long, old and complex history, lost in the mists of time.
 
-Configuration and database files like SSH keys, OpenPGP keyringsm,
+Configuration and database files like SSH keys, OpenPGP keyrings,
 password, group databases, or email forward files are synchronised to
 various hosts from the LDAP database. Most operations can be performed
 on the [db.torproject.org](https://db.torproject.org/) site or by [email](https://db.torproject.org/doc-mail.html).
@@ -460,7 +460,7 @@ In general, `ud-ldap`:
    email, DNS, and git servers
  * provides host metadata to Puppet
 
-This diagram covers those interdependencies at the time of writing.
+This diagram covers those inter-dependencies at the time of writing.
 
 ![LDAP architecture diagram](ldap/graph.svg)
 
@@ -470,7 +470,7 @@ An important part of `ud-ldap` is the `ud-generate`  command, which
 generates configuration files for each host. Then the `ud-replicate`
 command runs on each node to `rsync` those files. Both commands are
 ran from cron on regular intervals, the latter defined in Puppet, the
-former hardcoded to 15 minutes.
+former hard-coded to 15 minutes.
 
 More specifically, this is what happens:
 
@@ -504,7 +504,7 @@ one subdirectory per host.
 | `disabled-accounts`                | list of disabled accounts                                                         | `uid`, `userPassword` (*includes* inactive)                                                                                         |
 | `dns-sshfp`                        | per-host DNS entries (e.g. debian.org), if `DNS` in `exportOptions`               | see below                                                                                                                           |
 | `dns-zone`                         | user-managed DNS entries (e.g. debian.net), if `DNS` in `exportOptions`           | `dnsZoneEntry`                                                                                                                      |
-| `forward.alias`                    | .forward compatibilty, unused?                                                    | `uid`, `emailForward`                                                                                                               |
+| `forward.alias`                    | .forward compatibility, unused?                                                   | `uid`, `emailForward`                                                                                                               |
 | `group.tdb`                        | `group` file template, with only the group that have access to that host          | `uid`, `gidNumber`, `supplementaryGid`                                                                                              |
 | `last_update.trace`                | timestamps of last change to LDAP, keyring and last `ud-generate` run             | N/A                                                                                                                                 |
 | `mail-callout`                     | ?                                                                                 | mailCallout                                                                                                                         |
@@ -608,7 +608,7 @@ More files are handled specially by `ud-replicate`:
 
 ### Authentication mechanisms
 
-ud-ldap deals uses multiple mechanisms to authentify users and
+ud-ldap deals uses multiple mechanisms to authenticate users and
 machines.
 
  1. the web interface binds to the LDAP directory anonymously, or as
@@ -709,7 +709,7 @@ modified or deleted by the user through the email interface
 
 #### sudoPassword field format
 
-The `sudoPassword` field is special. It has 4 fields seperated by
+The `sudoPassword` field is special. It has 4 fields separated by
 spaces:
 
  1. a UUID
@@ -719,7 +719,7 @@ spaces:
     and the hashed password, joined by colons (`:`), primed with a
     secret key stored in `/etc/userdir-ldap/key-hmac-$UID` where UID
     is the numeric identifier of the calling user, generally `33`
-    (probably the webserver?) or `sshdist`? The secret key can also
+    (probably the web server?) or `sshdist`? The secret key can also
     overridden by the `UD_HMAC_KEY` environment variable
  3. the host list, either `*` (meaning all hosts) or a comma (`,`)
     separated list of hosts this password applies to
@@ -816,7 +816,7 @@ host. It can either enable or inhibit the creation of certain files.
  * `PRIVATE`: ship the `debian-private` mailing list registration file
  * `RTC-PASSWORDS`: ship the `rtc-passwords` file
  * `TOTP`: ship the `users.oath` file
- * `UNTRUSTED`: skip sudo passwords for this host unless explicitely
+ * `UNTRUSTED`: skip sudo passwords for this host unless explicitly
    set
  * `WEB-PASSWORDS`: ship the `web-passwords` file
 
@@ -983,7 +983,7 @@ looks at a word list, the GECOS fields and the old password. Partial
 updates are possible: if (say) the `rtcPassword` fields don't match
 but the `userPassword` fields do, the latter will be performed because
 it is done first. It is here that unconfirmed `sudo` passwords are set
-as well. It's the user's responsability to send the challenge response
+as well. It's the user's responsibility to send the challenge response
 by signed OpenPGP email afterwards. This script uses the `update.wml`
 template.
 
@@ -1014,10 +1014,10 @@ The `ipHostnumber` field is also used to lookup the host in the
 hosts the parent metal. This is, in turn, used in Hiera to change
 certain parameters, like Debian mirrors.
 
-Note that the above fields are explicitely imported in the
+Note that the above fields are explicitly imported in the
 `allnodeinfo` data structure, along with `sshRSAHostKey` and
 `mXRecord`, but those are not used. Furthermore, the `nodeinfo`
-datastructure imports all of the host's data, so there might be other
+data structure imports all of the host's data, so there might be other
 fields in use that I haven't found.
 
 Puppet connects to the LDAP server directly over LDAPS (port 636) and
@@ -1122,7 +1122,7 @@ gives us a hint on whether it is important or not.
 | `ud-fingerserv2.c`        | C      |     | same in C?                                                      |
 | `ud-forwardlist`          | Python |     | convert `.forward` files into LDAP configuration                |
 | `ud-generate`             | Python | x   | critical code path, generates all configuration files           |
-| `ud-gpgimport`            | Python |     | seems unused? "Key Ring Syncronization utility"                 |
+| `ud-gpgimport`            | Python |     | seems unused? "Key Ring Synchronization utility"                |
 | `ud-gpgsigfetch`          | Python |     | refresh signatures from a keyring? unused?                      |
 | `ud-groupadd`             | Python | x   | tries to create a group, possibly broken, not implemented by ud |
 | `ud-guest-extend`         | Python |     | "Query/Extend a guest account"                                  |
@@ -1211,7 +1211,7 @@ indefinitely for locked out users.
 `ud-ldap` keeps a full copy of all emails sent to
 `changes@db.torproject.org`, `ping@torproject.org` and
 `chpass@torproject.org` in `/srv/db.torproject.org/mail-logs/`. This
-includes personnally identifiable information (PII) like `Received-by`
+includes personally identifiable information (PII) like `Received-by`
 headers (which may include user's IP addresses), user's email
 addresses, SSH public keys, hashed sudo passwords, and junk mail. The
 mail server should otherwise follow normal mail server logging
@@ -1222,7 +1222,7 @@ The web interface keeps authentication tokens in
 and password information. Those get removed when a user logs out or
 after 10 minutes of inactivity, when the user returns. It's unclear
 what happens when a user forgets to logout and fails to return to the
-site. Webserver logs should otherwise follow the normal TPO policy.
+site. Web server logs should otherwise follow the normal TPO policy.
 
 The OpenLDAP server itself (`slapd`) keeps no logs.
 
@@ -1281,14 +1281,14 @@ reasons:
  * **old cryptographic primitives**: SHA-1 is used to hash `sudo`
    passwords, MD5 is used to hash user passwords, those hashes are
    communicated over OpenPGP_encrypted email but stored in LDAP in
-   cleartext. There is a "hack" present in the web interface to
+   clear-text. There is a "hack" present in the web interface to
    enforce MD5 passwords on logins, and the mail interface also has
-   MD5 hardcoded for password resets. Blowfish and HMAC-SHA-1 are also
+   MD5 hard-coded for password resets. Blowfish and HMAC-SHA-1 are also
    used to store and authenticate (respectively) LDAP passwords in the
    web interface. MD5 is used to hash usernames.
 
- * **rolls its own crypto**: ud-ldap ships its own wrapper around GnuPG,
-   implementing the (somewhat arcane) commandline dialect. it has not
+ * **rolls its own crypto**: `ud-ldap` ships its own wrapper around GnuPG,
+   implementing the (somewhat arcane) command-line dialect. it has not
    been determined if that implementation is either accurate or safe.
 
  * **email interface hard to use**: it has trouble with standard
@@ -1350,10 +1350,10 @@ writing, it is:
 
 It seems that upstream doesn't necessarily run released code, and we
 certainly don't: the above merge point had 47 commits on top of the
-previous release (0.3.96). The current release, as of october 2020, is
+previous release (0.3.96). The current release, as of October 2020, is
 0.3.97, and upstream already has 14 commits on top of it.
 
-The web interface is in a similar conendrum, except worse:
+The web interface is in a similar conundrum, except worse:
 
     22 files changed, 192 insertions(+), 648 deletions(-)
 
@@ -1369,7 +1369,7 @@ else, possibly removing LDAP as a database altogether.
 
 ### Must have
 
- * framework in use must be supported for the forseeable future
+ * framework in use must be supported for the foreseeable future
    (e.g. not Python 2)
  * unit tests or at least upstream support must be active
  * system must be simpler to understand and diagnose
@@ -1466,7 +1466,7 @@ to sysadmins, which would take on orphan services which would be
 harder to migrate inside containers.
 
 Because the current shell access provided is very limited, it is
-believe migration to containers would actually be not only feasable
+believe migration to containers would actually be not only feasible
 but also beneficial for users, as they would possibly get more
 privileges than they currently do.
 
@@ -1555,10 +1555,11 @@ Directory standard).
    account management and self-service password change", seems
    interesting
  * [GOsa][]: "administration frontend for user administration"
- * [phpLDAPadmin][]: like phpMyAdmin but for LDAP, for "power users",
+ * [phpLDAPadmin][]: like [phpMyAdmin][] but for LDAP, for "power users",
    long history of critical security issues
  * [web2ldap][]: web interface, python, still maintained, not exactly intuitive
 
+[phpMyAdmin]: https://www.phpmyadmin.net/
 [ldap-user-manager]: https://github.com/wheelybird/ldap-user-manager
 It might be simpler to rewrite `userdir-ldap-cgi` with [Django][], say
 using the [django-auth-ldap][] authentication plugin.