VPS پر Google کے بغیر CalDAV calendar کیسے بنائیں
Radicale کے ساتھ VPS پر CalDAV server بنائیں، TLS اور discovery ترتیب دیں، اور phone و laptop sync کریں۔ اس guide میں تقریباً 10 lines کی config شامل ہے۔
آپ کیا بنا رہے ہیں
Self-hosted calendar ایک VPS پر چلنے والا واحد CalDAV server ہے جسے آپ خود control کرتے ہیں۔ یہ TLS کے پیچھے چلتا ہے اور ہر شخص کے لیے ایک login ہوتا ہے۔ آپ کی جیب میں موجود phone اور میز پر رکھا laptop ایک ہی events دکھاتے ہیں، اور آپ کے partner کا laptop بھی یہی events دکھاتا ہے۔ درمیان میں کوئی Google account نہیں ہوتا۔
یہ کام self-hosted booking page سے مختلف ہے۔ Booking page اجنبی افراد کے لیے ہوتی ہے: یہ آپ کے دستیاب وقت کے slots شائع کرتی ہے اور کسی کو ایک slot منتخب کرنے دیتی ہے۔ Calendar server آپ کے اپنے devices کے لیے ہوتا ہے: یہ events محفوظ کرتا ہے اور ہر client کو ایک ہی حالت میں رکھتا ہے۔ لوگ اکثر دونوں چلاتے ہیں، اور booking tool اپنی availability اسی CalDAV server سے حاصل کرتا ہے جسے آپ یہاں بنائیں گے۔
یہ installation مختصر ہے۔ Radicale ایک Python package اور تقریباً دس lines کی configuration ہے۔ یہ setup پہلے ماہ کے بعد بھی قابلِ اعتماد رہتا ہے یا نہیں، اس کا فیصلہ TLS، discovery، ہر user کی collections اور backups کرتے ہیں۔ ذیل میں زیادہ تر جگہ انہی موضوعات کے لیے مختص ہے۔
CalDAV کیا ہے، اور یہ کیوں اہم ہے؟
CalDAV، HTTP کے ذریعے calendar sync کا پروٹوکول ہے۔ اسے RFC 4791 میں WebDAV کی extensions کے طور پر بیان کیا گیا ہے۔ WebDAV، web distributed authoring and versioning کا مخفف ہے اور RFC 4918 میں بیان کردہ اضافی HTTP methods کا مجموعہ ہے۔ Calendar ایک collection ہوتا ہے جو directory کی طرح کام کرتا ہے۔ ایک event اس collection کے اندر ایک file ہوتا ہے، جس میں iCalendar کا text format استعمال ہوتا ہے (RFC 5545)۔ یہی format آپ کی mail میں موجود .ics attachments کے لیے بھی استعمال ہوتا ہے۔
Clients عام HTTP استعمال کرتے ہیں، جس میں چند اضافی methods شامل ہوتے ہیں۔ PROPFIND یہ معلوم کرتا ہے کہ یہاں کیا موجود ہے اور اس کی کون سی properties ہیں۔ REPORT کسی filtered حصے کے لیے درخواست کرتا ہے، مثلاً کسی date range کے تمام events۔ PUT ایک event لکھتا ہے، جبکہ DELETE اسے حذف کرتا ہے۔ ہر event میں UID line ہوتی ہے۔ یہی identifier دو devices کو یہ طے کرنے میں مدد دیتا ہے کہ وہ ایک ہی event دیکھ رہے ہیں، نہ کہ اس کی الگ copy۔
اصل فائدہ portability ہے، اور CalDAV استعمال کرنے کی بنیادی وجہ بھی یہی ہے۔ iOS، macOS، Thunderbird، Evolution اور DAVx⁵ کے ذریعے Android، سب CalDAV کو support کرتے ہیں۔ آپ کا data اس server تک محدود نہیں رہتا جسے آپ آج منتخب کرتے ہیں۔ Files کو کسی دوسرے CalDAV server پر منتقل کریں، clients کو نئے hostname کی طرف point کریں، اور باقی کچھ تبدیل نہیں ہوتا۔
CardDAV بھی اسی طریقے سے کام کرتا ہے۔ یہ contacts کے لیے یہی تصور ہے، جسے RFC 6352 میں بیان کیا گیا ہے، اور اس میں events کے بجائے vCard files محفوظ ہوتی ہیں۔ ذیل میں موجود ہر server ایک ہی account سے دونوں protocols فراہم کرتا ہے۔ اس لیے calendar کے کام کرنے کے بعد address book کو صرف checkbox منتخب کرنا ہوتا ہے۔
کون سا CalDAV server چلانا چاہیے؟
Radicale وہ کم سے کم حل ہے جو کام کرتا ہے۔ یہ Python پر چلتا ہے، اسے database کی ضرورت نہیں ہوتی، اور data plain files کے folder میں محفوظ ہوتا ہے۔ یہ guide اسے اس لیے استعمال کرتی ہے کہ گھریلو calendar کو اس سے زیادہ کی ضرورت نہیں ہوتی، اور رات کے تین بجے خراب ہونے والی چیزیں بھی بہت کم ہوتی ہیں۔
Baikal وہ option ہے جس میں web admin panel موجود ہے۔ یہ PHP اور sabre/dav library پر چلتا ہے، users اور calendars کو SQLite یا MySQL میں محفوظ کرتا ہے، اور command line کے بجائے browser میں کسی شخص کو شامل کرنے دیتا ہے۔ جب accounts اکثر شامل یا حذف ہوتے رہیں تو اسے منتخب کریں۔
Nextcloud اس وقت موزوں ہے جب calendar کئی features میں سے صرف ایک ہو۔ اس کے ساتھ calendar، contacts، files اور mobile app ملتے ہیں، لیکن اس کے لیے PHP-FPM، database اور background job runner درکار ہوتے ہیں۔ اگر آپ کی اصل ضرورت کے مقابلے میں یہ setup زیادہ بھاری لگے تو Nextcloud کے ہلکے متبادل اس trade-off کا احاطہ کرتے ہیں، جبکہ self-hosted file sync اس دوسری بنیادی وجہ کا احاطہ کرتا ہے جس کے لیے لوگ Nextcloud install کرتے ہیں۔
DAViCal طویل عرصے سے موجود PostgreSQL option ہے۔ اسے صرف اس صورت میں دیکھیں جب آپ پہلے ہی PostgreSQL چلا رہے ہوں اور calendar data اسی میں محفوظ رکھنا چاہتے ہوں۔
Ubuntu 24.04 پر Radicale انسٹال کریں
8 October 2026 کو tag کیا گیا Radicale 3.8.3، 11 October 2026 تک موجودہ release ہے۔ اسے اپنے الگ virtual environment میں انسٹال کریں، اور bcrypt extra شامل کریں جس پر نیچے دی گئی password file انحصار کرتی ہے۔
sudo apt update
sudo apt install -y python3-venv apache2-utils nginx
sudo useradd --system --user-group --home-dir / --shell /usr/sbin/nologin radicale
sudo install -d -o radicale -g radicale -m 750 /var/lib/radicale/collections
sudo install -d -m 750 -o root -g radicale /etc/radicale
sudo python3 -m venv /opt/radicale/venv
sudo /opt/radicale/venv/bin/pip install --upgrade 'radicale[bcrypt]'virtual environment صرف طرزِ انتخاب نہیں ہے۔ sudo pip install radicale کو system Python میں چلانے سے error: externally-managed-environment آتا ہے، کیونکہ Ubuntu اپنے Python کو apt کی ملکیت کے طور پر نشان زد کرتا ہے تاکہ pip packaged files کو overwrite نہ کر سکے۔
/etc/radicale/config لکھیں:
[server]
hosts = 127.0.0.1:5232
[auth]
type = htpasswd
htpasswd_filename = /etc/radicale/users
htpasswd_encryption = autodetect
[storage]
filesystem_folder = /var/lib/radicale/collectionshosts جان بوجھ کر loopback پر bind ہوتا ہے۔ nginx TLS terminate کرتا ہے اور درخواستیں اس port پر forward کرتا ہے، اس لیے Radicale براہِ راست internet کے سامنے نہیں آتا۔ 0.0.0.0:5232 کی upstream مثال ایک unencrypted service کو public کرتی ہے جو passwords قبول کرتی ہے۔ یہاں یہی وہ واحد غلطی ہے جو اہم ہے۔
اب accounts بنائیں۔ -B bcrypt منتخب کرتا ہے، جسے Radicale htpasswd_encryption = autodetect کے ذریعے پڑھتا ہے، جب اوپر کی گئی radicale[bcrypt] install سے bcrypt module موجود ہو:
sudo htpasswd -B -c /etc/radicale/users you
sudo htpasswd -B /etc/radicale/users partner
sudo chown root:radicale /etc/radicale/users
sudo chmod 640 /etc/radicale/users-c file بناتا ہے اور اس میں موجود تمام مواد truncate کر دیتا ہے۔ اسے صرف پہلے user کے لیے استعمال کریں۔ مہینوں بعد دوبارہ htpasswd -B -c چلانے سے پہلے user کے بعد شامل کیے گئے تمام accounts حذف ہو جاتے ہیں۔ اس کی علامت یہ ہوتی ہے کہ ایک شخص کامیابی سے sync کرتا ہے، جبکہ باقی سب کو ایسا password prompt ملتا رہتا ہے جو کبھی ختم نہیں ہوتا۔ SHA-512 crypt (-5) یہاں قابلِ استعمال نہیں ہے: htpasswd نے Apache 2.4.59 میں SHA-2 support حاصل کیا، جبکہ Ubuntu 24.04 میں apache2-utils 2.4.58 شامل ہے، جس کے htpasswd میں -5 flag موجود نہیں ہے۔
/etc/systemd/system/radicale.service بنائیں، جو Radicale documentation میں موجود unit سے اخذ کی گئی ہے:
[Unit]
Description=CalDAV and CardDAV server
After=network.target
Requires=network.target
[Service]
ExecStart=/opt/radicale/venv/bin/python -m radicale
Restart=on-failure
User=radicale
UMask=0027
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
NoNewPrivileges=true
ReadWritePaths=/var/lib/radicale/
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now radicale
curl -i http://127.0.0.1:5232/درست نتیجہ 401 Unauthorized ہے، جس میں WWW-Authenticate header شامل ہو: اس کا مطلب ہے کہ service listening کر رہی ہے اور authentication فعال ہے۔ Connection refused کا مطلب ہے کہ اس address پر کچھ بھی listening نہیں کر رہا۔ عام طور پر اس کی وجہ یہ ہوتی ہے کہ service start نہیں ہوئی یا اس کے بعد exit ہو گئی۔ journalctl -u radicale -n 50 اس option کا نام دکھاتا ہے جسے service نے reject کیا۔ ProtectSystem=strict اس service کے لیے filesystem کو read only mount کرتا ہے، اس لیے ReadWritePaths=/var/lib/radicale/ وہ line ہے جو اسے کوئی event save کرنے دیتی ہے۔ اس line کو ہٹا دیں تو reads جاری رہیں گے، لیکن ہر write fail ہو جائے گا۔
TLS اختیاری نہیں ہے، کیونکہ clients plaintext کنکشن قبول نہیں کرتے
یہ setup HTTP Basic کے ذریعے authentication کرتا ہے۔ یہی وہ واحد scheme ہے جسے Radicale قبول کرتا ہے، اور Basic ہر request کے ساتھ user:password کو base64 میں encode کرکے بھیجتا ہے۔ Base64 encoding ہے، encryption نہیں۔ plain HTTP پر آپ password فون اور server کے درمیان موجود ہر network کو پورا دن، ہر sync کے دوران بھیج دیتے ہیں۔
clients یہ پابندی خود نافذ کرتے ہیں۔ Radicale کی documentation کے مطابق macOS Calendar.app unsecured HTTP پر credentials بھیجنے سے خاموشی سے انکار کر سکتی ہے، اور iOS بھی اسی طرح برتاؤ کرتا ہے۔ account configured دکھائی دیتا ہے، لیکن sync کبھی نہیں ہوتا اور پڑھنے کے لیے کوئی error بھی موجود نہیں ہوتا۔
پہلے cal.example.com کے لیے ایک A record VPS کی طرف point کریں، کیونکہ certificate authority اس کی جانچ کرتی ہے۔ پھر /etc/nginx/sites-available/cal.example.com بنائیں:
server {
listen 80;
server_name cal.example.com;
location / {
proxy_pass http://localhost:5232/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_pass_header Authorization;
}
location = /.well-known/caldav { return 301 https://$host/; }
location = /.well-known/carddav { return 301 https://$host/; }
}proxy header کی چاروں lines Radicale کی documentation سے لی گئی ہیں۔ انہیں اسی طرح رکھیں۔
sudo ln -s /etc/nginx/sites-available/cal.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d cal.example.com
curl -i -u you https://cal.example.com/nginx -t، syntax is ok اور test is successful دکھاتا ہے۔ صرف اس کے بعد reload کریں، کیونکہ broken file کے ساتھ reload کرنے سے پرانی config چلتی رہتی ہے اور غلطی اگلے restart تک چھپی رہتی ہے۔ Certbot site file کو براہ راست edit کرتا ہے: یہ certificate install کرتا ہے، block کو port 443 پر منتقل کرتا ہے، اور port 80 سے redirect شامل کرتا ہے۔ آخری curl password طلب کرتا ہے اور اسے 200 واپس کرنا چاہیے، جو Radicale کا اپنا web interface ہے۔ 502 Bad Gateway کا مطلب ہے کہ nginx چل رہا ہے، لیکن اسے port 5232 سے کوئی درست جواب نہیں ملا۔ اس کی عام وجہ یہ ہے کہ Radicale وہاں listening نہیں کر رہا۔
فون پر account شامل کرنے میں ناکامی کیوں ہوتی ہے؟
اس کی وجہ discovery ہے۔ RFC 6764 میں بتایا گیا ہے کہ client hostname کو calendar URL میں کیسے تبدیل کرتا ہے۔ یہ _caldavs._tcp SRV record تلاش کرتا ہے، پھر https://cal.example.com/.well-known/caldav کے لیے request بھیجتا ہے اور DAV root پر redirect کی توقع کرتا ہے۔ اس کے بعد یہ current-user-principal کے لیے، پھر اس principal کے calendar-home-set کے لیے request بھیجتا ہے، اور تب جا کر آپ کے calendars دکھائی دیتے ہیں۔ فون server کے لیے صرف ایک field فراہم کرتا ہے، اس لیے ہر مرحلہ خودکار طور پر کامیاب ہونا چاہیے۔
curl -sI https://cal.example.com/.well-known/caldavدرست جواب HTTP/2 301 ہے، جس میں location: https://cal.example.com/ header شامل ہو۔ وہاں موجود 404 عام طور پر اس وجہ سے ہوتا ہے کہ iOS کہتا ہے کہ account information کی تصدیق نہیں ہو سکتی، جبکہ اسی network پر Thunderbird کام کرتا ہے۔ Thunderbird آپ کے درج کردہ مکمل URL کو استعمال کرتا ہے، اس لیے اسے redirect کی ضرورت نہیں پڑتی۔
Redirect target server پر منحصر ہوتا ہے۔ site کے root پر چلنے والا Radicale / کی طرف redirect کرتا ہے۔ Radicale خود اس path پر پہنچنے والی request کے لیے 301 جواب دیتا ہے، اس لیے nginx rules redirect بنانے کے بجائے اسے واضح کرتی ہیں۔ Baikal کے ساتھ شامل sample rules status 308 کے ذریعے /dav.php کی طرف redirect کرتی ہیں۔ Nextcloud /remote.php/dav/ کی طرف redirect کرتا ہے۔
کیلنڈر بنائیں اور ایک کیلنڈر اپنے شریکِ حیات کے ساتھ شیئر کریں
بہت سے clients کیلنڈر نہیں بنا سکتے، صرف اسے subscribe کر سکتے ہیں۔ browser میں https://cal.example.com/ کھولیں، you کے طور پر login کریں، اور وہیں کیلنڈر بنائیں۔ disk پر یہ /var/lib/radicale/collections/collection-root/you/ کے اندر محفوظ ہوگا، جہاں folder name کے لیے generated identifier استعمال ہوگا۔
Radicale کا default rights backend owner_only ہے: authenticated account اپنی collections کو /USERNAME/ کے اندر پڑھ اور لکھ سکتا ہے، اس کے علاوہ کسی اور چیز تک رسائی نہیں ہوتی۔ زیادہ تر گھروں کے لیے یہ درست setting ہے، اور کیلنڈر شیئر کرنے کا سب سے آسان طریقہ ایک تیسرا account ہے۔ htpasswd کے ساتھ household بنائیں، اس login کے تحت shared calendar بنائیں، اور ہر device پر اسے دوسرے CalDAV account کے طور پر شامل کریں۔ یہ ہر client پر کام کرتا ہے، iOS پر بھی، کیونکہ کیلنڈر اسی account کے اپنے home میں موجود ہوتا ہے۔
جب زیادہ باریک control درکار ہو تو rule based rights استعمال کریں۔ /etc/radicale/config میں یہ شامل کریں:
[rights]
type = from_file
file = /etc/radicale/rightsپھر /etc/radicale/rights چلائیں، اور Radicale documentation میں موجود example کو بنیاد بنائیں:
[root]
user: .+
collection:
permissions: R
[principal]
user: .+
collection: {user}
permissions: RW
[own-calendars]
user: .+
collection: {user}/[^/]+
permissions: rw
[shared-household]
user: you|partner
collection: you/2f0a9c1e-1f4c-4c2b-9a1b-0d2f7a5c9e11
permissions: rwبڑے اور چھوٹے حروف کے الگ معنی ہیں۔ R اور W ان collections کو پڑھتے اور لکھتے ہیں جو calendars یا address books نہیں ہیں، کیونکہ principal folder اسی نوعیت کا ہوتا ہے۔ r اور w خود calendars کو پڑھتے اور لکھتے ہیں۔ اس identifier کو اوپر دیے گئے storage path میں موجود اپنے کیلنڈر کے اصل folder name سے تبدیل کریں۔
ایک اہم حد یہ ہے: جو client صرف calendar home set پڑھتا ہے، وہ کسی دوسرے user کے path کے اندر موجود کیلنڈر نہیں دکھائے گا، کیونکہ discovery وہاں تلاش نہیں کرتی۔ Thunderbird اور DAVx⁵ اسے مکمل URL کے ذریعے شامل کر سکتے ہیں۔ iOS ایسا نہیں کر سکتا، اسی لیے shared account کا طریقہ ہمیشہ کام کرتا ہے۔
کلائنٹس ترتیب دیں، کیونکہ self-hosted calendars عموماً اسی مرحلے پر ناکام ہوتے ہیں
iPhone اور iPad۔ Settings کھولیں، پھر Calendar کھولیں۔ حالیہ iOS versions میں یہ Apps کے اندر ہوتا ہے۔ اس کے بعد Calendar Accounts، Add Account، Other، Add CalDAV Account منتخب کریں۔ Server کے طور پر cal.example.com درج کریں، پھر user name اور password درج کریں۔ Description صرف ایک label ہے۔ اگر account save نہ ہو تو اسے دوبارہ کھولیں۔ Advanced view میں Use SSL، port اور مکمل account URL دکھائی دیتے ہیں۔ URL paste کرنے سے discovery مکمل طور پر نظرانداز ہو جاتی ہے۔
Android۔ اس میں built-in CalDAV client موجود نہیں ہے۔ F-Droid یا Google Play سے DAVx⁵ install کریں۔ Base URL https://cal.example.com/ استعمال کرتے ہوئے user name کے ساتھ account شامل کریں، پھر مطلوبہ calendars منتخب کریں۔ DAVx⁵ Android calendar provider میں data لکھتا ہے، اس لیے events اسی calendar app میں ظاہر ہوتے ہیں جو آپ پہلے سے استعمال کرتے ہیں۔
Thunderbird۔ New Calendar، On the Network منتخب کریں، پھر user name اور location https://cal.example.com/ درج کریں۔ یہ دستیاب calendars کی فہرست دکھاتا ہے اور پوچھتا ہے کہ کون سے calendars شامل کرنے ہیں۔
macOS۔ System Settings، Internet Accounts، Add Other Account، CalDAV منتخب کریں۔ Account Type کو Manual پر مقرر کریں، پھر وہی user name، password اور server address درج کریں۔
CalDAV ایک polling protocol ہے۔ specification میں push شامل نہیں ہے، اس لیے laptop پر شامل کیا گیا event اسی لمحے phone پر نہیں پہنچتا بلکہ اگلی sync پر ظاہر ہوتا ہے۔ ہر client میں ایسا interval مقرر کریں جو آپ کے لیے قابل قبول ہو۔ یہ بھی یاد رکھیں کہ phone پر مختصر interval battery زیادہ استعمال کرتا ہے۔
صرف files پر مشتمل store کا backup لیں
Radicale میں آپ کا calendar ایک directory ہے جس میں .ics files ہوتی ہیں، ہر event کے لیے ایک file، اور ہر collection کے لیے ایک چھوٹی properties file ہوتی ہے۔ جو بھی طریقہ directory کو copy کرتا ہے، وہ اس کا backup لے لیتا ہے۔ آپ backup کو less سے کھول کر تصدیق کر سکتے ہیں کہ اس میں حقیقی events موجود ہیں۔ یہ اس database dump کے مقابلے میں حقیقی فائدہ ہے جسے آپ پڑھ نہیں سکتے۔
sudo systemctl stop radicale
sudo tar czf /root/radicale-$(date +%F).tar.gz -C /var/lib/radicale collections
sudo systemctl start radicaleArchive تیار ہونے میں جتنے چند seconds لگتے ہیں، اتنی دیر کے لیے service روک دیں، تاکہ files پڑھے جانے کے وقت کوئی client write کے دوران درمیان میں نہ ہو۔ اس کے بعد archive کو server سے باہر copy کریں، کیونکہ اسی VPS پر موجود backup اس failure سے محفوظ نہیں رہتا جس کے لیے آپ تیاری کر رہے ہیں۔ Restore کا طریقہ الٹ ہے: extract کریں، sudo chown -R radicale:radicale /var/lib/radicale/collections چلائیں، اور service شروع کریں۔ ہر client اپنے calendars کی local copy بھی رکھتا ہے، اس لیے وہ laptop جس نے failure کے بعد sync نہیں کیا، آپ کے data کی دوسری copy ہوتا ہے۔
Baikal یا Nextcloud کب بہتر انتخاب ہے
Baikal 0.12.1، 5 August 2026 کو جاری ہوا اور اسے PHP 8.2 یا اس کے بعد کا ورژن درکار ہے۔ اسے web root سے باہر unpack کریں اور صرف اس کی html directory کو expose کریں:
sudo apt install -y php-fpm php-sqlite3 php-xml php-mbstring php-curl unzip
cd /tmp
curl -LO https://github.com/sabre-io/Baikal/releases/download/0.12.1/baikal-0.12.1.zip
sudo unzip -q baikal-0.12.1.zip -d /srv
sudo chown -R www-data:www-data /srv/baikal/Specific /srv/baikal/configیہ دونوں directories ہی وہ واحد مقامات ہیں جہاں web server لکھتا ہے، اس لیے کسی اور مقام کو writable بنانے کی ضرورت نہیں۔ اپنے nginx server block میں Baikal سے متعلق حصے یہ ہیں:
root /srv/baikal/html;
index index.php;
location ~ /(\.ht|Core|Specific|config) { deny all; }
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location = /.well-known/caldav { return 308 /dav.php; }
location = /.well-known/carddav { return 308 /dav.php; }nginx reload کریں، browser میں site کھولیں، اور setup wizard admin account اور SQLite database بنائے گا۔ Client setup Radicale جیسا ہی ہے۔ Server address کے طور پر https://cal.example.com/ استعمال کریں، کیونکہ well-known rule discovery کو /dav.php پر بھیجتا ہے۔
Nextcloud کا انتخاب اسی وقت مناسب ہے جب آپ اسی login کے تحت files اور phone app بھی چاہتے ہوں۔ اس کا DAV root /remote.php/dav/ ہے، اور یہی discovery rules یہاں بھی لاگو ہوتے ہیں۔ ان میں سے کسی بھی سروس کو container میں چلانے سے PHP versions آپ کے host سے الگ رہتے ہیں: VPS پر Docker Compose میں compose file اور اس کے سامنے reverse proxy کی وضاحت ہے، جبکہ 2026 میں self-host کرنا کیا فائدہ مند ہے اس بات کا فیصلہ کرنے کے لیے مناسب جگہ ہے کہ آپ اس راستے پر کس حد تک آگے بڑھنا چاہتے ہیں۔
خرابی کی صورتیں اور نظر آنے والی strings
ہر sync پر 401 واپس آتا ہے۔ یا تو password file سے اس کے accounts دوسرے htpasswd -c کی وجہ سے ختم ہو گئے ہیں، یا radicale user اسے پڑھ نہیں سکتا۔ sudo -u radicale cat /etc/radicale/users سے جانچ کریں؛ وہاں permission denied ملنا اصل وجہ ہے، اور حل group radicale کے ساتھ mode 640 مقرر کرنا ہے۔ Radicale ہر ناکام login کے بعد default طور پر ایک second بھی انتظار کرتا ہے، اس لیے stale password والا client rejected دکھائی دینے کے بجائے سست محسوس ہوتا ہے۔
nginx، PROPFIND پر 405 جواب دیتا ہے۔ URL کو static file کے طور پر serve کیا جا رہا ہے، اس لیے WebDAV method، Radicale تک نہیں پہنچتا۔ Endpoint کی براہ راست جانچ کریں:
curl -u you -X PROPFIND -H "Depth: 0" -i https://cal.example.com/you/فعال DAV collection، 207 Multi-Status جواب دیتی ہے۔ کوئی بھی دوسرا جواب اس بات کی علامت ہے کہ request web server پر رک گئی۔
فون account کی تصدیق نہیں کر سکتا، لیکن browser درست کام کرتا ہے۔ اس کی دو عام وجوہات ہیں۔ Well-known redirect موجود نہیں، جس کی جانچ اوپر دیے گئے curl سے کی جاتی ہے۔ یا certificate chain نامکمل ہے۔ Browsers missing intermediate کو حاصل کر کے اس مسئلے کو عموماً چھپا دیتے ہیں، لیکن iOS ایسا نہیں کرتا۔ Shell سے جانچ کریں:
openssl s_client -connect cal.example.com:443 -servername cal.example.com </dev/nullVerify return code: 0 (ok) تلاش کریں۔ اگر یہ ناکام ہو تو nginx config میں cert.pem کی طرف اشارہ ہے، حالانکہ اسے fullchain.pem کی طرف اشارہ کرنا چاہیے۔
Import کے بعد duplicate events بن جاتے ہیں۔ ہر event میں UID شامل ہوتا ہے، اور clients اسے identity سمجھتے ہیں۔ اگر ایسا ہی file کسی ایسے tool کے ذریعے دو بار import کیا جائے جو identifiers دوبارہ بناتا ہے، تو دو events پیدا ہو جاتے ہیں جنہیں کوئی چیز کبھی merge نہیں کرے گی۔ ایک device پر اضافی copies حذف کریں اور deletion کو sync ہونے دیں۔
Reboot کے بعد سب کچھ کام کرنا بند کر دیتا ہے۔ Service ہاتھ سے start کی گئی تھی۔ sudo systemctl is-enabled radicale، disabled دکھاتا ہے، اور sudo systemctl enable --now radicale اسے مستقل طور پر درست کر دیتا ہے۔
FAQ
کیا self-hosted CalDAV سرور کے لیے TLS واقعی ضروری ہے؟
ہاں۔ Radicale HTTP Basic authentication استعمال کرتا ہے، اس لیے password ہر request پر base64 encoded حالت میں بھیجا جاتا ہے، اور base64 کو آسانی سے اصل شکل میں تبدیل کیا جا سکتا ہے۔ Clients بھی اس کا تقاضا کرتے ہیں: macOS Calendar.app غیر محفوظ HTTP پر credentials بھیجنے سے خاموشی سے انکار کر سکتا ہے، اور iOS بھی اسی طرح عمل کرتا ہے۔ اس لیے account محفوظ ہوتا ہوا دکھائی دیتا ہے، لیکن کبھی sync نہیں ہوتا۔ sudo certbot --nginx -d cal.example.com پورا کام انجام دیتا ہے۔
Thunderbird میں account شامل ہو جاتا ہے، لیکن میرے phone میں کیوں ناکام ہوتا ہے؟
Thunderbird آپ کا درج کردہ مکمل URL استعمال کرتا ہے۔ Phone میں صرف ایک server field ہوتا ہے، اس لیے وہ RFC 6764 discovery پر انحصار کرتا ہے۔ SRV record نہ ہونے کی صورت میں وہ https://cal.example.com/.well-known/caldav کو request بھیجتا ہے اور DAV root پر redirect کی توقع کرتا ہے۔ اگر اس request کا جواب 404 ہو تو phone عموماً بتاتا ہے کہ وہ account کی تصدیق نہیں کر سکتا۔ nginx میں location = /.well-known/caldav { return 301 https://$host/; } شامل کریں، پھر curl -sI https://cal.example.com/.well-known/caldav سے تصدیق کریں کہ جواب 301 اور location header فراہم کرتا ہے۔ iOS کی advanced settings میں مکمل account URL paste کرنے سے discovery مکمل طور پر bypass ہو جاتی ہے۔
کیا دو افراد ایک calendar شیئر کر سکتے ہیں؟
ہاں، اور قابلِ اعتماد طریقہ shared login ہے۔ htpasswd کے ذریعے تیسرا account بنائیں، shared calendar اسی account کے تحت رکھیں، اور اسے ہر device پر دوسرے CalDAV account کے طور پر شامل کریں۔ Radicale کی rights file اس کے بجائے کسی named user کو دوسرے user کے path کے اندر موجود ایک collection پر read اور write access دے سکتی ہے۔ لیکن جو client صرف اپنے calendar home set کو پڑھتا ہے، وہ اسے کبھی display نہیں کرے گا۔ اس لیے یہ طریقہ iOS کے بجائے Thunderbird اور DAVx⁵ کے لیے موزوں ہے۔
VPS بند ہو جائے تو میرے events کا کیا ہوتا ہے؟
Radicale میں store plain text ہوتا ہے: /var/lib/radicale/collections/collection-root/ کے تحت ہر event کے لیے ایک .ics file موجود ہوتی ہے۔ آپ اسے tar کے ذریعے back up کر سکتے ہیں اور less سے پڑھ سکتے ہیں۔ Restore کے لیے extract کریں، chown -R radicale:radicale چلائیں، اور service start کریں۔ ہر synced client مقامی copy بھی رکھتا ہے، اس لیے failure سے پہلے up-to-date موجود laptop پر آپ کے calendar کی مکمل دوسری copy موجود ہوتی ہے۔
کیا CalDAV server میرے contacts بھی sync کرتا ہے؟
Contacts کے لیے CardDAV استعمال ہوتا ہے۔ یہ RFC 6352 میں بیان کردہ sibling protocol ہے، جو events کے بجائے vCard files محفوظ کرتا ہے۔ Radicale، Baikal اور Nextcloud اسے اسی account اور اسی hostname سے serve کرتے ہیں۔ Android پر DAVx⁵ ایک ہی account سے calendars اور contacts sync کرتا ہے۔ iOS پر اسی credentials کے ساتھ CardDAV type کا دوسرا account شامل کرنا ہوتا ہے۔ اسی لیے /.well-known/carddav redirect کو CalDAV redirect کے ساتھ nginx config میں شامل کیا جاتا ہے۔