Differences from version 6 to 8



@@ -3,2 +2,0 @@

{toc}10in Yare Dragon


@@ -7 +5,4 @@

{code}zypper install radicale # Creates radicale:radicale system user automatically {/code}

zypper install radicale
# Creates radicale:radicale system user automatically

@@ -13 +14,12 @@

{code}[server] hosts = localhost:5232 [auth] type = htpasswd htpasswd_filename = /etc/radicale/users htpasswd_encryption = autodetect [storage] filesystem_folder = /srv/radicale/collections {/code}

[server]
hosts = localhost:5232
[auth]
type = htpasswd
htpasswd_filename = /etc/radicale/users
htpasswd_encryption = autodetect
[storage]
filesystem_folder = /srv/radicale/collections

@@ -20,2 +32,2 @@

<code>ReadWritePaths=/var/lib/radicale/collections /srv/radicale/
</code>
ReadWritePaths=/var/lib/radicale/collections /srv/radicale/

@@ -26 +38 @@

<code>mkdir -p /srv/radicale/collections
mkdir -p /srv/radicale/collections

@@ -30 +42 @@

</code>

@@ -37 +49 @@

<code># Create directory structure
# Create directory structure

@@ -41,2 +53,2 @@

# Props files — collection-root needs one too!
echo '{}' > /srv/radicale/collections/collection-root/.Radicale.props
# Props files — collection-root needs one too!
echo '{}' > /srv/radicale/collections/collection-root/.Radicale.props

@@ -44,2 +56,2 @@

cat > /srv/radicale/collections/collection-root/lsces/.Radicale.props << 'EOF'
{"D:displayname": "lsces"}
cat > /srv/radicale/collections/collection-root/lsces/.Radicale.props << 'EOF'
{"D:displayname": "lsces"}

@@ -48,2 +60,2 @@

cat > /srv/radicale/collections/collection-root/lsces/calendar/.Radicale.props << 'EOF'
{"C:supported-calendar-component-set": "VEVENT,VJOURNAL,VTODO", "D:displayname": "Personal Calendar", "tag": "VCALENDAR"}
cat > /srv/radicale/collections/collection-root/lsces/calendar/.Radicale.props << 'EOF'
{"C:supported-calendar-component-set": "VEVENT,VJOURNAL,VTODO", "D:displayname": "Personal Calendar", "tag": "VCALENDAR"}

@@ -52,2 +64,2 @@

cat > /srv/radicale/collections/collection-root/lsces/contacts/.Radicale.props << 'EOF'
{"D:displayname": "Personal Contacts", "tag": "VADDRESSBOOK"}
cat > /srv/radicale/collections/collection-root/lsces/contacts/.Radicale.props << 'EOF'
{"D:displayname": "Personal Contacts", "tag": "VADDRESSBOOK"}

@@ -57 +69 @@

</code>

@@ -62,2 +74,2 @@

<code>htpasswd -B -c /etc/radicale/users lsces
</code>
htpasswd -B -c /etc/radicale/users lsces

@@ -68 +80 @@

<code>systemctl daemon-reload
systemctl daemon-reload

@@ -72 +84 @@

</code>

@@ -77 +89 @@

<code>location /dav/ {
location /dav/ {

@@ -85 +97 @@

</code>

@@ -87 +99 @@

**Both Authorization headers needed — nginx strips it without explicit passthrough!**

Both Authorization headers needed — nginx strips it without explicit passthrough!


@@ -91 +103,3 @@

**Calendar export** — Nextcloud UI: Calendar → Edit → Export → saves `.ics` Radicale requires **one event per file** — split the export:

Calendar export — Nextcloud UI:

Calendar → Edit → Export → saves `.ics`
Radicale requires **one event per file** — split the export:


@@ -94 +108 @@

<code>import re, os
import re, os

@@ -96 +110 @@

with open('personal.ics', 'r') as f:
with open('personal.ics', 'r') as f:

@@ -99,4 +113,4 @@

header = content[:content.index('BEGIN:VEVENT')]
footer = 'END:VCALENDARn'
events = re.findall('BEGIN:VEVENT.*?END:VEVENT', content, re.DOTALL)
os.makedirs('/srv/radicale/split', exist_ok=True)
header = content[:content.index('BEGIN:VEVENT')]
footer = 'END:VCALENDARn'
events = re.findall('BEGIN:VEVENT.*?END:VEVENT', content, re.DOTALL)
os.makedirs('/srv/radicale/split', exist_ok=True)

@@ -105,2 +119,2 @@

uid = re.search('UID:(.*?)n', event).group(1).strip()
with open(f'/srv/radicale/split/{uid}.ics', 'w') as f:
uid = re.search('UID:(.*?)n', event).group(1).strip()
with open(f'/srv/radicale/split/{uid}.ics', 'w') as f:

@@ -108 +122 @@

f.write(event + 'n')
f.write(event + 'n')

@@ -111,2 +125,2 @@

print(f'Split {len(events)} events')
</code>
print(f'Split {len(events)} events')

@@ -117 +131 @@

<code>import re, os
import re, os

@@ -119 +133 @@

with open('contacts.vcf', 'r') as f:
with open('contacts.vcf', 'r') as f:

@@ -122,2 +136,2 @@

contacts = re.findall('BEGIN:VCARD.*?END:VCARD', content, re.DOTALL)
os.makedirs('/srv/radicale/split_contacts', exist_ok=True)
contacts = re.findall('BEGIN:VCARD.*?END:VCARD', content, re.DOTALL)
os.makedirs('/srv/radicale/split_contacts', exist_ok=True)

@@ -126,4 +140,4 @@

uid = re.search('UID:(.*?)n', contact)
uid = uid.group(1).strip() if uid else f'contact_{contacts.index(contact)}'
with open(f'/srv/radicale/split_contacts/{uid}.vcf', 'w') as f:
f.write(contact + 'n')
uid = re.search('UID:(.*?)n', contact)
uid = uid.group(1).strip() if uid else f'contact_{contacts.index(contact)}'
with open(f'/srv/radicale/split_contacts/{uid}.vcf', 'w') as f:
f.write(contact + 'n')

@@ -131,2 +145,2 @@

print(f'Split {len(contacts)} contacts')
</code>
print(f'Split {len(contacts)} contacts')

@@ -137 +151 @@

<code># Calendar events
# Calendar events

@@ -139 +153 @@

uid=$(basename "$f" .ics)
uid=$(basename "$f" .ics)

@@ -142,4 +156,4 @@

-H "Content-Type: text/calendar"
--data-binary @"$f"
"https://rdm1.uk/dav/lsces/calendar/${uid}.ics"
echo "$uid"
-H "Content-Type: text/calendar"
--data-binary @"$f"
"https://rdm1.uk/dav/lsces/calendar/${uid}.ics"
echo "$uid"

@@ -150 +164 @@

uid=$(basename "$f" .vcf)
uid=$(basename "$f" .vcf)

@@ -153,4 +167,4 @@

-H "Content-Type: text/vcard"
--data-binary @"$f"
"https://rdm1.uk/dav/lsces/contacts/${uid}.vcf"
echo "$uid"
-H "Content-Type: text/vcard"
--data-binary @"$f"
"https://rdm1.uk/dav/lsces/contacts/${uid}.vcf"
echo "$uid"

@@ -158 +172 @@

</code>

@@ -162 +176,11 @@

**Thunderbird** — Add new calendar/contacts: - Network → CalDAV/CardDAV - URL: `https://yourdomain/dav/username/calendar/` **DAVx⁵ (Android)** — Add account: - Base URL: `https://yourdomain/dav/username/` - Auto-discovers both calendar and contacts

  • Thunderbird — Add new calendar/contacts:
  • Network → CalDAV/CardDAV
  • URL: https://yourdomain/dav/username/calendar/
  • DAVx⁵ (Android) — Add account:
  • Base URL:https://yourdomain/dav/username/
  • Auto-discovers both calendar and contacts

  • @@ -163,0 +188,2 @@

    Developed with Claude AI

    assistance - Anthropic - April 2026

    Page History
    Date/CommentUserIPVersion
    28 Apr 2026 (12:39 UTC)
    —
    Lester Caine192.168.1.2548
    Current • Source
    Lester Caine192.168.1.2547
    View • Compare • Difference • Source
    Lester Caine192.168.1.2546
    View • Compare • Difference • Source
    Lester Caine192.168.1.2545
    View • Compare • Difference • Source
    Lester Caine192.168.1.2544
    View • Compare • Difference • Source
    Lester Caine192.168.1.2543
    View • Compare • Difference • Source
    Lester Caine192.168.1.2542
    View • Compare • Difference • Source
    Lester Caine192.168.1.2541
    View • Compare • Difference • Source