docs: Anhaenge, Hintergrund-Jobs und neue Variablen im README
Dokumentiert auch den ehrlichen Haken der ATTACH-Links: sie muessen ohne Login funktionieren, weil externe Kalender-Clients keinen mitschicken koennen, und sind damit unbefristet gueltige Capability-URLs. Mit dem Abschalter, falls das fuer eine Installation nicht tragbar ist. Nebenbei die seit dem Monorepo-Merge falsche Aussage korrigiert, die mobilen Apps laegen in eigenen Repos. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e2a7edf421
commit
cd8aba74b6
@@ -24,6 +24,7 @@ A clean, self-hosted calendar application with support for CalDAV, Google Calend
|
|||||||
- Create, edit, and delete events with title, description, location, and time
|
- Create, edit, and delete events with title, description, location, and time
|
||||||
- All-day events
|
- All-day events
|
||||||
- Per-event color overrides
|
- Per-event color overrides
|
||||||
|
- **Attachments** — PDFs, images and text files on local events (10 MB each, 10 per event)
|
||||||
- iCal event overrides (hide or edit individual events from subscriptions)
|
- iCal event overrides (hide or edit individual events from subscriptions)
|
||||||
- Dim past events option
|
- Dim past events option
|
||||||
|
|
||||||
@@ -102,11 +103,15 @@ Configuration is done via environment variables. The `install.sh` script generat
|
|||||||
| `SECRET_KEY` | *(auto-generated)* | JWT signing key — use a strong random value in production |
|
| `SECRET_KEY` | *(auto-generated)* | JWT signing key — use a strong random value in production |
|
||||||
| `PORT` | `8080` | Server port |
|
| `PORT` | `8080` | Server port |
|
||||||
| `HOST` | `0.0.0.0` | Bind address |
|
| `HOST` | `0.0.0.0` | Bind address |
|
||||||
| `DATA_DIR` | `./data` | Directory for SQLite database and avatars |
|
| `DATA_DIR` | `./data` | Directory for the SQLite database, avatars, branding and attachments |
|
||||||
| `GOOGLE_CLIENT_ID` | — | Google OAuth2 Client ID *(optional)* |
|
| `GOOGLE_CLIENT_ID` | — | Google OAuth2 Client ID *(optional)* |
|
||||||
| `GOOGLE_CLIENT_SECRET` | — | Google OAuth2 Client Secret *(optional)* |
|
| `GOOGLE_CLIENT_SECRET` | — | Google OAuth2 Client Secret *(optional)* |
|
||||||
| `GOOGLE_REDIRECT_URI` | — | e.g. `https://yourdomain.com/api/google/callback` *(optional)* |
|
| `GOOGLE_REDIRECT_URI` | — | e.g. `https://yourdomain.com/api/google/callback` *(optional)* |
|
||||||
| `PUBLIC_BASE_URL` | *(derived)* | Public origin behind a reverse proxy — **required for SSO** |
|
| `PUBLIC_BASE_URL` | *(derived)* | Public origin behind a reverse proxy — **required for SSO** and for attachment links in CalDAV |
|
||||||
|
| `ATTACHMENT_PUBLIC_LINKS` | `1` | `0` disables the unauthenticated attachment URLs (see below) |
|
||||||
|
| `SCHEDULER_ENABLED` | `1` | `0` disables all background jobs |
|
||||||
|
| `ATTACHMENT_SWEEP_HOURS` | `24` | How often orphaned attachments are cleaned up |
|
||||||
|
| `ICAL_REFRESH_MINUTES` | `15` | How often iCal subscriptions are checked in the background |
|
||||||
| `OIDC_PROVIDERS` | — | Comma-separated provider keys, e.g. `authentik` *(optional)* |
|
| `OIDC_PROVIDERS` | — | Comma-separated provider keys, e.g. `authentik` *(optional)* |
|
||||||
|
|
||||||
Per provider `<KEY>` listed in `OIDC_PROVIDERS` (variable names are uppercased):
|
Per provider `<KEY>` listed in `OIDC_PROVIDERS` (variable names are uppercased):
|
||||||
@@ -138,8 +143,8 @@ Adds an SSO button to the login screen **alongside** password login. With
|
|||||||
- iOS: `com.scarriffleservices.calendarr.ios:/oauth2redirect`
|
- iOS: `com.scarriffleservices.calendarr.ios:/oauth2redirect`
|
||||||
- Android: `com.scarriffle.calendarr:/oauth2redirect`
|
- Android: `com.scarriffle.calendarr:/oauth2redirect`
|
||||||
|
|
||||||
The mobile apps are separate repositories (`Calendarr-IOS`, `Calendarr-Android`)
|
The mobile apps live in this repository under `ios/` and `android/`, and
|
||||||
and authenticate as **public** clients via AppAuth — PKCE, no client secret.
|
authenticate as **public** clients via AppAuth — PKCE, no client secret.
|
||||||
Set `OIDC_<KEY>_MOBILE_CLIENT_ID` to the client id they use; without it the apps
|
Set `OIDC_<KEY>_MOBILE_CLIENT_ID` to the client id they use; without it the apps
|
||||||
show no SSO button.
|
show no SSO button.
|
||||||
|
|
||||||
@@ -194,6 +199,59 @@ same as 2FA users.
|
|||||||
**Rollback:** remove `OIDC_PROVIDERS` and restart. Accounts created via SSO
|
**Rollback:** remove `OIDC_PROVIDERS` and restart. Accounts created via SSO
|
||||||
remain and must be removed (or given a password) by an admin.
|
remain and must be removed (or given a password) by an admin.
|
||||||
|
|
||||||
|
### Attachments
|
||||||
|
|
||||||
|
Events in **local** calendars can carry files: PDFs, images (PNG/JPEG/WebP/GIF)
|
||||||
|
and text files (TXT/Markdown/CSV), up to **10 MB per file and 10 per event**.
|
||||||
|
Events from CalDAV, Google, Home Assistant or iCal subscriptions cannot — they
|
||||||
|
are fetched live from their own server and have no record here to attach to.
|
||||||
|
|
||||||
|
Files are stored under `DATA_DIR/attachments`; **back that up together with the
|
||||||
|
database**, or a restored database will point at files that no longer exist.
|
||||||
|
|
||||||
|
Who may attach or remove a file is the same rule as who may edit the event:
|
||||||
|
the calendar's owner, group members, and anyone with a read-write share. A
|
||||||
|
read-only share can view and download. Private events of other users expose
|
||||||
|
neither their attachments nor their number.
|
||||||
|
|
||||||
|
**Attachments in external calendar clients.** The generated ICS carries an
|
||||||
|
`ATTACH` line per file, so Apple Calendar, Thunderbird and DAVx5 show the
|
||||||
|
attachment and can download it. Those clients cannot send a login, so the URL
|
||||||
|
has to work without one: each attachment gets its own unguessable 256-bit
|
||||||
|
token, and anyone who has that URL can fetch the file.
|
||||||
|
|
||||||
|
Weigh that honestly. The link only ever reaches clients that were already
|
||||||
|
allowed to read the calendar, and it dies when the attachment is deleted — but
|
||||||
|
it is long-lived, it ends up in plain text in the client's local calendar
|
||||||
|
store, and it would appear in a reverse-proxy access log. If that is not
|
||||||
|
acceptable for your deployment, set `ATTACHMENT_PUBLIC_LINKS=0`: no `ATTACH`
|
||||||
|
line is written and the public URL stops answering. Attachments then work in
|
||||||
|
the web UI and the mobile apps only.
|
||||||
|
|
||||||
|
`PUBLIC_BASE_URL` must be set for the links to be correct behind a reverse
|
||||||
|
proxy; without a usable base URL the `ATTACH` line is omitted entirely.
|
||||||
|
|
||||||
|
### Background jobs
|
||||||
|
|
||||||
|
The server runs two periodic jobs in-process:
|
||||||
|
|
||||||
|
| Job | Interval | What it does |
|
||||||
|
|---|---|---|
|
||||||
|
| `attachments.sweep` | 24 h | Removes attachment records whose event is gone, and files with no record |
|
||||||
|
| `ical.refresh` | 15 min | Re-fetches iCal subscriptions that are due |
|
||||||
|
|
||||||
|
Attachments are normally cleaned up the moment an event, calendar or user is
|
||||||
|
deleted; the sweep is the safety net for what gets past that — an external
|
||||||
|
CalDAV client deleting an event, or a request that died mid-upload. It leaves
|
||||||
|
files younger than an hour alone, so it cannot race an upload in progress.
|
||||||
|
|
||||||
|
The iCal job only drives the same refresh the app already did on demand, so
|
||||||
|
subscription intervals are unchanged. What is new is that subscriptions stay
|
||||||
|
current while nobody has the app open.
|
||||||
|
|
||||||
|
Both jobs assume a single server process, which is how `main.py` starts
|
||||||
|
uvicorn. Running multiple workers would run every job once per worker.
|
||||||
|
|
||||||
### Google Calendar Setup
|
### Google Calendar Setup
|
||||||
|
|
||||||
1. Create a project in [Google Cloud Console](https://console.cloud.google.com/)
|
1. Create a project in [Google Cloud Console](https://console.cloud.google.com/)
|
||||||
|
|||||||
Reference in New Issue
Block a user