evolution: integrate with Radicale for vcard contacts storage
This commit is contained in:
@@ -87,6 +87,8 @@
|
||||
sane.ids.resolvconf.gid = 2009;
|
||||
sane.ids.smartd.uid = 2010;
|
||||
sane.ids.smartd.gid = 2010;
|
||||
sane.ids.radicale.uid = 2011;
|
||||
sane.ids.radicale.gid = 2011;
|
||||
|
||||
# found on graphical hosts
|
||||
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
||||
|
@@ -148,6 +148,7 @@
|
||||
./portfolio-filemanager.nix
|
||||
./playerctl.nix
|
||||
./qmk-udev-rules.nix
|
||||
./radicale.nix
|
||||
./rhythmbox.nix
|
||||
./ripgrep.nix
|
||||
./rofi
|
||||
|
@@ -1,7 +1,5 @@
|
||||
# evolution-data-server (e-d-s) exposes DBus services for managing contacts and calendars.
|
||||
#
|
||||
# TODO: setup plaintext backend (e.g. vcard import/export; or CardDAV with a plaintext backend like radicale)
|
||||
#
|
||||
# common users include:
|
||||
# - `folks` (for contacts only, used in turn by `gnome-calls`, `gnome-contacts`, et al.)
|
||||
# - `gnome-calendars`, along with several other calendar or todo/tasking apps
|
||||
@@ -69,6 +67,15 @@
|
||||
# - WEBCAL_DEBUG
|
||||
# - WEBDAV_DEBUG
|
||||
# - WEBDAV_NOTES_DEBUG
|
||||
#
|
||||
#
|
||||
# should you need to reconfigure the radicale stuff (e.g. add another collection):
|
||||
# - do so using `evolution`
|
||||
# - it will ask to auth against radicale: enter <user>, keep password field empty
|
||||
# - new `.source` files will appear under ~/.cache/evolution:
|
||||
# - these represent the collections: move them into ~/.config and give them stable names
|
||||
# - edit them to not have `parent=...` (this will allow them to connect w/o auth)
|
||||
# - then remove the `evolution` passwords from gnome-keyring to ensure reproducibility
|
||||
{ config, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.programs."evolution-data-server";
|
||||
@@ -81,7 +88,16 @@ in
|
||||
withGtk4 = false;
|
||||
};
|
||||
|
||||
suggestedPrograms = [
|
||||
# "gnome-keyring" # to save the empty password for my calendar
|
||||
# radicale acts as a CardDAV / CalDAV server:
|
||||
# evolution speaks to it over http port 5232
|
||||
# and it reads/writes vcard .vcf files to its own storage
|
||||
"radicale"
|
||||
];
|
||||
|
||||
sandbox.whitelistDbus = [ "user" ];
|
||||
sandbox.net = "localhost"; #< to reach radicale (TODO: restrict further)
|
||||
|
||||
persist.byStore.ephemeral = [
|
||||
".cache/evolution"
|
||||
@@ -89,13 +105,93 @@ in
|
||||
# - birthdays.source
|
||||
# - system-calendar.source
|
||||
# - system-proxy.source
|
||||
".config/evolution/sources"
|
||||
# ".config/evolution/sources"
|
||||
# ".local/share/evolution"
|
||||
];
|
||||
persist.byStore.private = [
|
||||
# ".cache/evolution/sources"
|
||||
# local data stores (e.g. addressbook, calendar) live in ~/.local/share/evolution
|
||||
".local/share/evolution"
|
||||
# ".local/share/evolution"
|
||||
# ".local/share/evolution/addressbook/system"
|
||||
# ".local/share/evolution/calendar/system"
|
||||
];
|
||||
|
||||
# radicale source: configured by building `evolution` and adding the account there.
|
||||
# the password (empty) was presumably saved to gnome-keyring.
|
||||
# fs.".config/evolution/sources/ec1438cee0ce00521a96cd266b980c20891c41cf.source".symlink.text = ''
|
||||
# fs.".config/evolution/sources/pkm.source".symlink.text = ''
|
||||
# [Data Source]
|
||||
# DisplayName=colin
|
||||
# Enabled=true
|
||||
# Parent=
|
||||
|
||||
# [Authentication]
|
||||
# Host=
|
||||
# Method=plain/password
|
||||
# Port=0
|
||||
# ProxyUid=system-proxy
|
||||
# RememberPassword=true
|
||||
# User=colin
|
||||
# CredentialName=
|
||||
# IsExternal=false
|
||||
|
||||
# [Collection]
|
||||
# BackendName=webdav
|
||||
# CalendarEnabled=true
|
||||
# ContactsEnabled=true
|
||||
# Identity=colin
|
||||
# MailEnabled=true
|
||||
# AllowSourcesRename=false
|
||||
# CalendarUrl=
|
||||
# ContactsUrl=http://localhost:5232
|
||||
# '';
|
||||
# file created by:
|
||||
# - after configuring `pkm.source` above, evolution should auto-discover collection items
|
||||
# and make them available as random UUIDs in e.g. `~/.cache/evolution/sources/pkm/<UUID>.source`.
|
||||
# - copy that file here, and rename it as desired.
|
||||
fs.".config/evolution/sources/pkm-contacts.source".symlink.text = ''
|
||||
[Data Source]
|
||||
DisplayName=git-synchronized PKM
|
||||
Enabled=true
|
||||
# Parent=pkm
|
||||
|
||||
[Authentication]
|
||||
Host=localhost
|
||||
Method=plain/password
|
||||
Port=5232
|
||||
ProxyUid=system-proxy
|
||||
RememberPassword=true
|
||||
User=colin
|
||||
CredentialName=
|
||||
IsExternal=false
|
||||
|
||||
[Security]
|
||||
Method=none
|
||||
|
||||
[Resource]
|
||||
Identity=contacts::http://localhost:5232/colin/pkm/
|
||||
|
||||
[WebDAV Backend]
|
||||
AvoidIfmatch=false
|
||||
CalendarAutoSchedule=false
|
||||
Color=
|
||||
DisplayName=git-synchronized PKM
|
||||
EmailAddress=
|
||||
ResourcePath=/colin/pkm/
|
||||
ResourceQuery=
|
||||
SslTrust=
|
||||
Order=4294967295
|
||||
Timeout=90
|
||||
|
||||
[Address Book]
|
||||
BackendName=carddav
|
||||
Order=0
|
||||
'';
|
||||
|
||||
gsettings."org/freedesktop/folks" = {
|
||||
primary-store = "eds:pkm-contacts";
|
||||
};
|
||||
|
||||
# e-d-s provides the following services:
|
||||
# - evolution-addressbook-factory (org.gnome.evolution.dataserver.AddressBook10)
|
||||
# - evolution-calendar-factory (org.gnome.evolution.dataserver.Calendar8)
|
||||
@@ -105,6 +201,7 @@ in
|
||||
# evolution-addressbook-factory is required for gnome-contacts to add/view contacts
|
||||
description = "evolution-addressbook-factory provides contacts storage/retrieval to dbus users";
|
||||
dependencyOf = [ "graphical-session" ];
|
||||
depends = [ "radicale" ];
|
||||
command = "${cfg.package}/libexec/evolution-addressbook-factory --keep-running";
|
||||
readiness.waitDbus = "org.gnome.evolution.dataserver.AddressBook10";
|
||||
};
|
||||
@@ -112,6 +209,7 @@ in
|
||||
# evolution-addressbook-factory is required by gnome-calendar to add/view events
|
||||
description = "evolution-calendar-factory provides calendar storage/retrieval to dbus users";
|
||||
dependencyOf = [ "graphical-session" ];
|
||||
depends = [ "radicale" ];
|
||||
command = "${cfg.package}/libexec/evolution-calendar-factory --keep-running";
|
||||
readiness.waitDbus = "org.gnome.evolution.dataserver.Calendar8";
|
||||
};
|
||||
|
59
hosts/common/programs/radicale.nix
Normal file
59
hosts/common/programs/radicale.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
# radicale is a CalDAV/CardDAV server.
|
||||
# it receives http queries from calendar or contacts managers
|
||||
# and translates that into reads/writes of vcard .vcf files in some persisted folder
|
||||
#
|
||||
# admin interface: <http://localhost:5232>
|
||||
# enter username: "colin", password: (empty)
|
||||
#
|
||||
# settings: <https://radicale.org/v3.html#configuration>
|
||||
#
|
||||
# TODO: this setup allows access to *anything* on the machine with net access;
|
||||
# but i don't really want e.g. my web browser to know all my personal contacts:
|
||||
# maybe run this in a net namespace? `JoinsNamespaceOf=evolution` (or vice versa)?
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.programs.radicale;
|
||||
in
|
||||
{
|
||||
sane.programs.radicale = {
|
||||
# sane.programs.radicale is a sentinel for the nixpkgs' radicale service,
|
||||
# which is well-sandboxed, and there's no benefit to having it on PATH
|
||||
packageUnwrapped = null;
|
||||
};
|
||||
|
||||
services.radicale = lib.mkIf cfg.enabled {
|
||||
enable = true;
|
||||
package = pkgs.radicale.overrideAttrs (upstream: {
|
||||
version = lib.warnIf (lib.versionOlder "3.3.1" upstream.version) "radicale outdated: remove src override" "3.3.1-unstable-2024-12-14";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "Kozea";
|
||||
repo = "Radicale";
|
||||
rev = "778f56cc4d7b828af6e2e472f2e7898db72dca22";
|
||||
hash = "sha256-Oy6LDI+gvAqwR5XRz7JmRWI7KrAUYTOzHfvJsBRyVmU=";
|
||||
};
|
||||
});
|
||||
settings.storage.type = "multifilesystem_nolock";
|
||||
settings.storage.use_cache_subfolder_for_history = true; #< requires radicale > 3.3.1
|
||||
settings.storage.use_cache_subfolder_for_item = true;
|
||||
settings.storage.use_cache_subfolder_for_synctoken = true;
|
||||
# settings.storage.filesystem_cache_folder = "/var/lib/radicale/cache";
|
||||
# settings.storage.filesystem_folder = "/path/to/storage"
|
||||
# settings.auth.type = "none"; # default: none
|
||||
};
|
||||
|
||||
# TODO: service is considered 'up' too early: we should wait, and notify once the http port is bound/listening
|
||||
systemd.services.radicale = lib.mkIf cfg.enabled {
|
||||
serviceConfig.User = lib.mkForce "colin";
|
||||
# serviceConfig.Group = "users";
|
||||
serviceConfig.ReadWritePaths = [
|
||||
"/mnt/persist/private/home/colin/knowledge/social/contacts/db"
|
||||
];
|
||||
unitConfig.RequiresMountsFor = [
|
||||
"/mnt/persist/private/home/colin/knowledge/social/contacts/db"
|
||||
];
|
||||
};
|
||||
|
||||
sane.fs = lib.optionals cfg.enabled {
|
||||
"/var/lib/radicale/collections/collection-root/colin/pkm".symlink.target = "/mnt/persist/private/home/colin/knowledge/social/contacts/db";
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user