diff --git a/docs/config.md b/docs/config.md
index df7751dd..c233a77e 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -121,6 +121,111 @@ Here's an example config using mostly the defaults (except for the cache directo
 Please also refer to the [rate limiting](#rate-limiting) settings below, specifically `visitor-attachment-total-size-limit`
 and `visitor-attachment-daily-bandwidth-limit`. Setting these conservatively is necessary to avoid abuse.
 
+## Access control
+By default, the ntfy server is open for everyone, meaning everyone can read and write to any topic. To restrict access
+to your own server, you can optionally configure authentication and authorization. 
+
+ntfy's auth is implemented with a simple SQLite-based backend. It implements two roles (`user` and `admin`) and per-topic
+`read` and `write` permissions using an access control list (ACL). Access control entries can be applied to users as well
+as the special everyone user (`*`), which represents anonymous API access. 
+
+To set up auth, simply configure the following two options:
+
+* `auth-file` is the SQLite user/access database; it is created automatically if it doesn't already exist
+* `auth-default-access` defines the default/fallback access if no access control entry is found; it can be
+  set to `read-write` (default), `read-only`, `write-only` or `deny-all`.
+
+Once configured, you can use the `ntfy user` command to add/modify/delete users (with either a `user` or an `admin` role).
+To control granular access to specific topics, you can use the `ntfy access` command to modify the access control list.
+
+### Example: private instance
+The easiest way to configure a private instance is to set `auth-default-access` to `deny-all` in the `server.yml`:
+
+``` yaml
+auth-file "/var/lib/ntfy/user.db"
+auth-default-access: "deny-all"
+```
+
+After that, simply create an `admin` user:
+
+```
+$ ntfy user add --role=admin phil
+Password: mypass
+Confirm: mypass
+User phil added with role admin 
+```
+
+Once you've done that, you can publish and subscribe using [Basic Auth](https://en.wikipedia.org/wiki/Basic_access_authentication) 
+with the given username/password. Here's a simple example:
+
+=== "Command line (curl)"
+    ```
+    curl \
+        -u phil:mypass \
+        -d "Look ma, with auth" \
+        ntfy.example.com/secrets
+    ```
+
+=== "ntfy CLI"
+    ```
+    ntfy publish ntfy.example.com/mytopic "Look ma, with auth"
+
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    XXXXXXXXXXX
+    ```
+
+=== "HTTP"
+    ``` http
+    POST /mytopic HTTP/1.1
+    Host: ntfy.sh
+    Authorization: Basic cGhpbDpteXBhc3M=
+
+    Backup successful 😀
+    ```
+=== "JavaScript"
+``` javascript
+fetch('https://ntfy.sh/mytopic', {
+method: 'POST', // PUT works too
+body: 'Backup successful 😀'
+})
+```
+
+=== "Go"
+``` go
+http.Post("https://ntfy.sh/mytopic", "text/plain",
+strings.NewReader("Backup successful 😀"))
+```
+
+=== "Python"
+``` python
+requests.post("https://ntfy.sh/mytopic",
+data="Backup successful 😀".encode(encoding='utf-8'))
+```
+
+=== "PHP"
+``` php-inline
+file_get_contents('https://ntfy.sh/mytopic', false, stream_context_create([
+'http' => [
+'method' => 'POST', // PUT also works
+'header' => 'Content-Type: text/plain',
+'content' => 'Backup successful 😀'
+]
+]));
+```
+
 ## E-mail notifications
 To allow forwarding messages via e-mail, you can configure an **SMTP server for outgoing messages**. Once configured, 
 you can set the `X-Email` header to [send messages via e-mail](publish.md#e-mail-notifications) (e.g.