Skip to content

Commit ba8ef2e

Browse files
committed
Docs: add FAQ with password reset, library mount, and Authentik OIDC setup
1 parent a960261 commit ba8ef2e

2 files changed

Lines changed: 145 additions & 0 deletions

File tree

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,12 @@ The live API is self-documented via OpenAPI. With the server running:
580580
581581
---
582582
583+
## FAQ
584+
585+
Common questions and troubleshooting tips are in [docs/faq.md](docs/faq.md).
586+
587+
---
588+
583589
## Contributing
584590
585591
Grimoire is open source and contributions are welcome — bug reports, feature ideas, docs, and code.

docs/faq.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Frequently Asked Questions
2+
3+
## I forgot my admin password. How do I reset it?
4+
5+
If you're locked out of your account, you can reset the password directly in the database by running a one-liner inside the running container:
6+
7+
```bash
8+
docker exec <container_name> python3 -c "
9+
from passlib.context import CryptContext
10+
import sqlite3
11+
pwd = CryptContext(schemes=['bcrypt_sha256']).hash('<your_new_password>')
12+
db = sqlite3.connect('/app/data/grimoire.db')
13+
db.execute(\"UPDATE users SET hashed_password = ? WHERE username = ?\", (pwd, '<your_username>'))
14+
db.commit()
15+
db.close()
16+
print('Done')
17+
"
18+
```
19+
20+
Replace `<container_name>`, `<your_new_password>`, and `<your_username>` with the correct values for your setup. The container name is typically `grimoire` unless you changed it in your compose file.
21+
22+
Alternatively, you can create a new admin account by [pre-seeding a users file](../README.md#pre-seeding-users) and restarting the stack.
23+
24+
---
25+
26+
## The scanner finds no books after I reorganized my library.
27+
28+
Grimoire expects a specific folder structure inside your library volume mount. The scanner looks for a **`books/`** subfolder at the root of the mount:
29+
30+
```
31+
/library/ ← volume mount target
32+
books/
33+
D&D 5e/
34+
Core Rules/
35+
Players Handbook.pdf
36+
Pathfinder/
37+
...
38+
maps/ ← optional
39+
tokens/ ← optional
40+
```
41+
42+
If your PDFs live directly under the mounted folder (e.g. `RPGs/<GameSystem>/...` without a `books/` subfolder), the scanner will find nothing.
43+
44+
**Fix** — mount your library folder as `/library/books` instead of `/library`:
45+
46+
```yaml
47+
volumes:
48+
- /path/to/your/rpgs:/library/books:ro
49+
- ./grimoire/data:/data
50+
```
51+
52+
This lets you keep your existing file structure on the host without adding an extra `books/` folder. After updating the compose file, restart the stack and trigger a rescan from the admin panel.
53+
54+
> **Note:** "Remove missing files" deletes database records for files that can't be found at their expected paths. If you moved files around on the host before the volume mount was correct, those records were removed. Re-mounting correctly and rescanning will re-add everything.
55+
56+
---
57+
58+
## How do I configure OIDC with Authentik?
59+
60+
Below is a complete setup for Authentik that maps groups to Grimoire roles and controls NSFW access via a separate group.
61+
62+
### 1. Create the groups
63+
64+
In Authentik, create these groups:
65+
66+
| Group | Purpose |
67+
|---|---|
68+
| `grimoire-admin` | Full admin access |
69+
| `grimoire-gm` | GM role |
70+
| `grimoire-player` | Player role |
71+
| `nsfw` | Grants explicit content access to non-admin users |
72+
73+
Assign your users to the appropriate groups.
74+
75+
### 2. Create a custom scope
76+
77+
Go to **Customization → Property Mappings** and create two **Scope Mappings**.
78+
79+
**Name: `Grimoire Groups`**
80+
**Scope: `groups`** — maps Authentik groups to Grimoire roles:
81+
82+
```python
83+
groups = [group.name for group in user.ak_groups.all()]
84+
85+
grimoire_groups = []
86+
if "grimoire-admin" in groups:
87+
grimoire_groups.append("admin")
88+
if "grimoire-gm" in groups:
89+
grimoire_groups.append("gm")
90+
if "grimoire-player" in groups:
91+
grimoire_groups.append("player")
92+
93+
return {"groups": grimoire_groups}
94+
```
95+
96+
**Name: `Grimoire Permissions`**
97+
**Scope: `permissions`** — controls explicit content access:
98+
99+
```python
100+
groups = [group.name for group in user.ak_groups.all()]
101+
102+
if "grimoire-admin" in groups:
103+
return {
104+
"permissions": {
105+
"viewNSFW": True
106+
}
107+
}
108+
109+
explicit = "nsfw" in groups
110+
111+
return {
112+
"permissions": {
113+
"viewNSFW": explicit
114+
}
115+
}
116+
```
117+
118+
### 3. Configure the provider
119+
120+
In your Authentik OAuth2/OIDC provider:
121+
122+
1. Open (or create) your **OAuth2/OpenID Provider**.
123+
2. Scroll to **Advanced Protocol Settings**.
124+
3. Under **Scopes**, click **Add** and select both `Grimoire Groups` and `Grimoire Permissions` from the list.
125+
4. Save the provider.
126+
5. Note your **Client ID** and **Client Secret** from the provider's overview page.
127+
128+
### 4. Configure Grimoire
129+
130+
In Grimoire **Settings → Authentication**:
131+
132+
1. Set **Issuer URL** to your Authentik application's issuer (e.g. `https://authentik.example.com/application/o/<app-slug>/`) and click **Autopopulate**.
133+
> Authentik's token issuer often differs from the provider URL. If login fails with an issuer mismatch, copy the `iss` value from a decoded token and paste it into the **Token Issuer** field.
134+
2. Paste your **Client ID** and **Client Secret**.
135+
3. Register the displayed **Redirect URI** in your Authentik provider.
136+
4. Set **Groups Claim** to `groups`.
137+
5. Set **Advanced Permissions Claim** to `permissions`.
138+
6. Enable **Auto-register** if you want accounts created automatically on first login.
139+
7. Enable **OpenID Connect**.

0 commit comments

Comments
 (0)