Skip to content

Calendar

The calendar service syncs events from your online accounts and shows them in the control center calendar. CalDAV providers (Nextcloud, iCloud, Fastmail, Radicale, mailbox.org, …) are talked to directly; Google Calendar is connected through a browser authorization flow. Events are read-only.

The simplest path is Settings → Services → Calendar → Add Account.

  • iCloud: choose iCloud, enter a local account id such as personal_icloud, your Apple Account email, and an Apple app-specific password.
  • CalDAV: choose CalDAV, enter a local account id such as home_nextcloud, the provider’s CalDAV discovery root, your username, and a provider app password.
  • Google: choose Google, enter a local account id such as work_google, then press Save and Connect. A browser opens for Google authorization.

Saving an account enables [calendar] automatically. The GUI writes account config to settings.toml using named tables like [calendar.account.personal_icloud]. CalDAV passwords and Google OAuth tokens are stored in state.toml under [calendar_credentials], not in user config files.

Account ids are local Noctalia identifiers. Use lowercase letters, digits, and underscores only. The GUI keeps an account id fixed after creation so existing config and credential keys are not removed or renamed.

Existing accounts can be edited from Settings → Services → Calendar. Google accounts expose the same name/color editor and include Save plus Save and Connect actions; both save the current editor values, and Save and Connect then opens browser authorization. The delete action is shown only for accounts created in settings.toml; accounts declared in ~/.config/noctalia/*.toml are never removed by the GUI.

[calendar]
enabled = true
refresh_minutes = 15
# iCloud CalDAV. The table name is the local account id.
[calendar.account.personal_icloud]
type = "caldav"
name = "Personal iCloud"
provider = "icloud"
username = "you@example.com"
color = "primary" # optional color role or hex color
calendars = [] # empty = all discovered calendars
# Generic CalDAV discovery root (Nextcloud, Fastmail, Radicale, mailbox.org, …)
[calendar.account.home_nextcloud]
type = "caldav"
name = "Home"
provider = "custom"
server_url = "https://cloud.example.com/remote.php/dav/"
username = "me"
calendars = ["personal"] # optional discovered collection ids; empty = all
# Google Calendar (authorized via Settings → Services → Calendar → Connect)
[calendar.account.work_google]
type = "google"
name = "Work"

Credentials are never stored in your config. CalDAV app-passwords and Google OAuth tokens live in state.toml (user-only readable) under [calendar_credentials].

Noctalia discovers CalDAV calendars from an account/server root, then syncs each selected calendar collection. You do not need to find the provider’s final calendar collection URL yourself.

The account id is the last segment of the named table. For [calendar.account.personal_icloud], the id is personal_icloud. Use short ids with lowercase letters, digits, and underscores only. The id is local to Noctalia; it does not need to match your email address or provider account name.

For manual CalDAV setup, store the password in state.toml. The password key is <id>_password, so [calendar.account.personal_icloud] uses personal_icloud_password:

[calendar_credentials]
personal_icloud_password = "provider-app-password"

The state file is normally at ~/.local/state/noctalia/state.toml, unless NOCTALIA_STATE_HOME or XDG_STATE_HOME is set.

For providers with two-factor authentication, create an app-specific password in the provider’s account security settings and use that value here. Your normal account password will usually fail.

Provider rules:

  • provider = "icloud" uses Apple’s built-in CalDAV discovery URL. Do not set server_url.
  • provider = "custom" requires server_url, which should be the provider’s CalDAV discovery root, not a specific calendar collection.
  • calendars = [] syncs every discovered calendar that supports events.
  • calendars = ["id"] syncs only discovered collection ids. Collection ids are the decoded final path segment of the discovered calendar URL. Leave this empty first, then narrow it manually after confirming discovery.

iCloud needs an Apple app-specific password. Use your Apple Account email as username.

In Settings, choose iCloud and use your Apple app-specific password in the App Password field. For manual TOML, use provider = "icloud" and do not set server_url; Noctalia uses Apple’s CalDAV discovery URL automatically.

[calendar.account.icloud_personal]
type = "caldav"
name = "Personal iCloud"
provider = "icloud"
username = "me@example.com"
calendars = []
[calendar.account.icloud_family]
type = "caldav"
name = "Family iCloud"
provider = "icloud"
username = "family@example.com"
calendars = []
[calendar_credentials]
icloud_personal_password = "apple-app-specific-password"
icloud_family_password = "another-apple-app-specific-password"

Do not use a public .ics sharing URL or your normal iCloud password. Noctalia connects to your private iCloud CalDAV account with the app-specific password.

Common iCloud failures:

  • 401 or repeated auth failures: regenerate an Apple app-specific password and store it under the exact <id>_password key.
  • No events from one calendar: leave calendars = [] first to verify discovery, then select collection ids only after confirming what was discovered.
  • Shared calendars may have their own collection ids; leave calendars = [] to include them all.

In Settings, choose Google, then press Save and Connect. For manual TOML, add a named account table with type = "google", enable the calendar service, then open Settings → Services → Calendar, edit the account, and press Save and Connect. A browser tab opens for Google’s consent screen; approve it and the tab confirms completion. Tokens are obtained through the noctalia OAuth broker (api.noctalia.dev) — no Google Cloud project or client secret is required on your side. Access is calendar.readonly.

If a Google account later shows as disconnected (revoked or expired), edit the account and press Save and Connect again to reauthorize.

[shell].offline_mode = true disables all calendar network traffic; the last successfully synced events remain available from the on-disk cache.