Shlink वापरून स्वतःचे URL Shortener कसे तयार करावे
Docker Compose द्वारे VPS वर Shlink इन्स्टॉल करा. या मार्गदर्शकामध्ये Postgres डेटाबेस सेटअप, API की जनरेशन, HTTPS कॉन्फिगरेशन आणि क्लिक स्टॅट्स ट्रॅकिंगची संपूर्ण प्रक्रिया दिली आहे.
तुम्ही काय तयार करत आहात
Self-hosted URL shortener हा एक छोटा सर्व्हर आहे, जो लांब लिंकला तुमच्या मालकीच्या छोट्या लिंकमध्ये रूपांतरित करतो आणि प्रत्येक क्लिकची मोजणी करतो. यासाठी Shlink हा उत्तम पर्याय आहे: हे ओपन सोर्स आहे, Docker image म्हणून उपलब्ध आहे आणि एका कंटेनर व डेटाबेसमध्ये संपूर्ण काम करते. हे मार्गदर्शक Shlink ला एका VPS वर, एका खऱ्या शॉर्ट डोमेनच्या मागे, HTTPS, API key, QR codes आणि क्लिक स्टॅट्ससह कसे सेट करायचे ते सांगते.
दोन घटकांमुळे हे एखाद्या व्यावसायिक शॉर्टनरसारखे काम करते. API सर्व्हर रिडायरेक्ट्सना प्रतिसाद देतो आणि डेटा साठवतो. वेब क्लायंट हे एक स्वतंत्र स्टॅटिक ॲप आहे, जे तुमच्या ब्राउझरमधून त्या API शी संवाद साधते. तुम्ही दोन्ही चालवू शकता किंवा फक्त API चालवून कमांड लाईनवरून ते नियंत्रित करू शकता.
येथे दिलेले व्हर्जन नंबर्स जुलै 2026 पर्यंतचे आहेत: Shlink 5.1 आणि shlink-web-client 4.8.
सर्वप्रथम सर्व्हरवर एक छोटा डोमेन पॉइंट करा
डोमेन हेच तुमचे उत्पादन आहे. s.example.com/abc123 ही ती लिंक आहे जी लोक पाहतात, त्यामुळे काहीही इन्स्टॉल करण्यापूर्वी एक छोटा डोमेन निवडा. Shlink प्रत्येक शॉर्ट URL सोबत डोमेन साठवते, त्यामुळे नंतर ते बदलल्यास तुम्ही आधी वाटलेल्या सर्व लिंक्स काम करणे बंद करतील.
तुमच्या शॉर्ट डोमेनसाठी एक DNS A record तयार करा, जो तुमच्या VPS च्या सार्वजनिक IPv4 ॲड्रेसकडे निर्देश करेल. जर सर्व्हरकडे IPv6 असेल, तर एक AAAA record देखील जोडा. त्यानंतर, पुढे जाण्यापूर्वी तो डोमेन रिझॉल्व्ह होत असल्याची खात्री करा.
dig +short s.example.com Aआउटपुटमध्ये तुमच्या सर्व्हरचा ॲड्रेस दिसला पाहिजे. जर आउटपुट रिकामे असेल, तर याचा अर्थ असा की रेकॉर्ड अजून प्रोपॅगेट झालेला नाही. अशा स्थितीत पुढील सर्व पायऱ्या गोंधळात टाकणाऱ्या पद्धतीने अपयशी ठरतील, कारण ज्या नावाचे रिझोल्यूशन होत नाही, त्यासाठी TLS (transport layer security) प्रमाणपत्र जारी करता येत नाही.
Compose फाईल
Shlink ला डेटाबेसची आवश्यकता असते. चाचणीसाठी SQLite चालू शकते, परंतु जर तुम्हाला डेटा टिकवून ठेवायचा असेल तर Postgres हाच योग्य पर्याय आहे. कारण व्हिजिट्सच्या नोंदी वाढत जातात आणि Postgres इंडेक्स व एकाच वेळी होणारे रायट्स (concurrent writes) अधिक चांगल्या प्रकारे हाताळते. हे /opt/shlink/compose.yaml मध्ये ठेवा.
services:
shlink:
image: shlinkio/shlink:stable
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
DEFAULT_DOMAIN: s.example.com
IS_HTTPS_ENABLED: "true"
DB_DRIVER: postgres
DB_HOST: database
DB_NAME: shlink
DB_USER: shlink
DB_PASSWORD: ${DB_PASSWORD}
depends_on:
- database
database:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_DB: shlink
POSTGRES_USER: shlink
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- shlink_db:/var/lib/postgresql/data
web-client:
image: shlinkio/shlink-web-client:stable
restart: unless-stopped
ports:
- "127.0.0.1:8081:8080"
volumes:
shlink_db:दोन्ही पब्लिश केलेले पोर्ट्स 127.0.0.1 वर बाइंड होतात, त्यामुळे पुढील विभागातील रिव्हर्स प्रॉक्सी सेटअप होईपर्यंत इंटरनेटवरून काहीही ॲक्सेस करता येणार नाही. Docker स्वतःचे फॉरवर्डिंग नियम होस्ट फायरवॉलच्या आधी लिहितो, याचा अर्थ असा की साधी 8080:8080 ओळ फायरवॉल बंद असलेल्या सर्व्हरवरही ॲप उघडे करू शकते. लूपबॅक ॲड्रेसवर बाइंड केल्यामुळे हे टाळता येते. याच पद्धतीने तुम्ही चालवणाऱ्या कोणत्याही ॲपला हाच नियम लागू होतो आणि याची अधिक माहिती Docker Compose on a VPS वरील मार्गदर्शिकेमध्ये दिली आहे.
डेटाबेसचा पासवर्ड compose फाईलच्या शेजारी असलेल्या .env फाईलमधून येतो, त्यामुळे तो कधीही YAML मध्ये समाविष्ट होत नाही.
sudo mkdir -p /opt/shlink
printf 'DB_PASSWORD=%s\n' "$(openssl rand -base64 24)" | sudo tee /opt/shlink/.env
sudo chmod 600 /opt/shlink/.envहे सुरू करा आणि API कार्यान्वित होताना पहा.
cd /opt/shlink
sudo docker compose up -d
sudo docker compose logs -f shlinkपहिली सुरुवात डेटाबेस मायग्रेशन्स पूर्ण करते, त्यामुळे नंतरच्या वेळेपेक्षा याला जास्त वेळ लागतो. जेव्हा सर्व स्थिर होईल, तेव्हा सेवा स्थानिक पातळीवर प्रतिसाद देत आहे का ते तपासा.
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/rest/health200 चा अर्थ असा की API जिवंत आहे आणि डेटाबेस कनेक्शन योग्यरित्या काम करत आहे. येथे 500 येण्याचे कारण बहुतेक वेळा डेटाबेसशी संबंधित असते: .env मधील DB_PASSWORD हे Postgres तयार करताना वापरलेल्या पासवर्डशी जुळत नाही. याचे कारण असे की Postgres इमेज केवळ रिकामी डेटा डिरेक्टरी इनिशिअलाईज करतानाच POSTGRES_PASSWORD वाचते. व्हॉल्यूम काढून टाकून पुन्हा सुरुवात केल्याशिवाय पासवर्ड बदलल्याचा कोणताही परिणाम होत नाही.
त्याच्या समोर HTTPS समाप्त करा
Shlink पोर्ट 8080 वर साधे HTTP सर्व्ह करते. TLS हे reverse proxy मध्ये हाताळले पाहिजे आणि सर्वात महत्त्वाची सेटिंग म्हणजे मूळ host name पुढे पाठवणे. Shlink हे Host हेडर वाचून एखादा short code कोणत्या domain शी संबंधित आहे हे ठरवते, त्यामुळे जे हेडर rewrite करते असा proxy अस्तित्वात असलेल्या लिंक्ससाठी 404 प्रतिसाद देतो आणि चुकीच्या domain वर भेट दिलेल्या सांख्यिकी (stats) जोडतो.
server {
server_name s.example.com;
listen 80;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}त्यानंतर प्रमाणपत्र (certificate) जारी करा. नूतनीकरण टायमरसह (renewal timer) संपूर्ण प्रक्रिया Ubuntu 24.04 वरील nginx साठी Certbot मार्गदर्शिका मध्ये दिली आहे.
sudo certbot --nginx -d s.example.comcompose फाईलमधील IS_HTTPS_ENABLED: "true" मुळेच Shlink त्याच्याद्वारे परत केलेल्या short URLs मध्ये https:// प्रिंट करते. हे स्वतःहून TLS सक्षम करत नाही. याला HTTPS proxy च्या मागे false ठेवा, अन्यथा API द्वारे परत केलेली प्रत्येक लिंक ही http:// लिंक असेल जी नंतर redirect होते. यामुळे एक अतिरिक्त round trip लागते आणि web client मध्ये ते चुकीचे दिसते.
API key तयार करणे
API key शिवाय कोणतीही सेवा API शी संवाद साधू शकत नाही. कंटेनरमधील CLI वापरून एक की तयार करा.
sudo docker compose exec shlink shlink api-key:generate --name "web client"ही कमांड की फक्त एकदाच दाखवते. ती आताच कॉपी करा, कारण ती हॅश स्वरूपात साठवली जाते आणि पुन्हा दाखवता येत नाही. shlink api-key:list कमांड प्रत्येक कीचे नाव आणि ती सक्रिय आहे की नाही हे दाखवते, परंतु की स्वतः कधीही दाखवत नाही. shlink api-key:disable आणि कीचे नाव वापरून तुम्ही ती रद्द (revoke) करू शकता.
प्रत्येक REST call मध्ये की X-Api-Key हेडरमध्ये असणे आवश्यक आहे.
curl -H "X-Api-Key: YOUR_KEY" https://s.example.com/rest/v3/short-urlsshortUrls की असलेला JSON ऑब्जेक्ट म्हणजे की योग्यरित्या काम करत आहे. INVALID_API_KEY असलेला 401 प्रतिसाद म्हणजे की चुकीची आहे, बंद (disabled) केली आहे किंवा तिची मुदत संपली आहे.
कमांड लाइनवरून शॉर्ट लिंक्स तयार करणे
लिंक्स तयार करण्याचा CLI हा सर्वात जलद मार्ग आहे आणि तो स्क्रिप्टिंगसाठी उत्तम आहे.
sudo docker compose exec shlink shlink short-url:create https://example.com/a/very/long/path
sudo docker compose exec shlink shlink short-url:create https://example.com/docs --custom-slug docs --tag reference--custom-slug वापरल्यामुळे तुम्हाला जनरेट केलेल्या कोडऐवजी वाचनीय लिंक मिळते. स्लग (slugs) हे प्रत्येक डोमेनसाठी युनिक असतात, त्यामुळे जर एखादा स्लग आधीच वापरला असेल, तर दुसरी विनंती अयशस्वी होते; ती जुन्या लिंकवर ओव्हरराईट होत नाही. --tag चा वापर पुन्हा पुन्हा करता येतो आणि टॅग्सच्या (tags) मदतीने तुम्ही अशा लिंक्स एकत्र करू शकता ज्यांची एकत्रित आकडेवारी तुम्हाला नंतर पाहायची आहे.
अस्तित्वात असलेल्या लिंक्सची यादी करा आणि त्यानंतर एखाद्या विशिष्ट लिंकची ट्रॅफिक तपासा.
sudo docker compose exec shlink shlink short-url:list
sudo docker compose exec shlink shlink short-url:visits docsshort-url:visits प्रत्येक क्लिकसाठी एक ओळ प्रिंट करते, ज्यामध्ये तारीख, रेफरर (referrer) आणि युजर एजंट (user agent) यांची माहिती असते. जोपर्यंत तुम्ही GEOLITE_LICENSE_KEY एनवायरमेंट व्हेरिएबल सेट करत नाही, तोपर्यंत देश आणि शहराचे कॉलम रिकामे राहतात. हे एक मोफत MaxMind की आहे, ज्याचा वापर करून Shlink हे GeoLite2 डेटाबेस डाउनलोड करते. हे सेट न केल्यास, भेटींची नोंद केली जाते, परंतु त्यांचे भौगोलिक स्थान समजत नाही.
वेब क्लायंट आणि QR कोड
वेब क्लायंट आता 127.0.0.1:8081 वर उपलब्ध आहे आणि त्याला स्वतःच्या प्रॉक्सी एन्ट्रीची आवश्यकता आहे, किंवा जर तुम्हाला तो सार्वजनिक करायचा नसेल तर तुम्ही SSH टनेल वापरू शकता. पहिल्यांदा लोड झाल्यावर तो सर्व्हर URL आणि API की विचारतो. तिथे https://s.example.com आणि तुम्ही तयार केलेली की प्रविष्ट करा. क्लायंट या दोन्ही गोष्टी ब्राउझर स्टोरेजमध्ये ठेवतो आणि थेट तुमच्या API ला कॉल करतो, त्यामुळे कोणताही डेटा इतर कोणाकडेही जात नाही. इंटरफेस आणि API वेगळे करणे ही एक महत्त्वाची पद्धत आहे, कारण याच पद्धतीमुळे Halcyon मीडिया सर्व्हरमध्ये कोणताही बदल न करता Jellyfin लायब्ररीला 1990 च्या दशकातील रेंटल स्टोअरचे रूप देऊ शकते.
QR कोडसाठी कोणत्याही कॉन्फिगरेशनची आवश्यकता नाही. कोणत्याही शॉर्ट URL च्या शेवटी /qr-code जोडा, म्हणजे API तुम्हाला ती प्रतिमा देईल.
https://s.example.com/docs/qr-code?size=500&format=svg&margin=20size हे पिक्सेलमध्ये रुंदी दर्शवते आणि 50 ते 1000 पर्यंतची मूल्ये स्वीकारते, ज्यामध्ये 300 हे डीफॉल्ट मूल्य आहे. format हे png किंवा svg असू शकते. margin हे कोडच्या सभोवतालची रिकामी जागा (quiet space) पिक्सेलमध्ये दर्शवते आणि तयार झालेली प्रतिमा ही कोडचा आकार अधिक दोनदा मार्जिन इतकी असते. जर कोड लहान आकारात छापला किंवा अंशतः झाकला गेला तरी तो स्कॅन व्हावा असे वाटत असेल, तर errorCorrection=Q जोडा.
सेवा सुरू ठेवा
URL shortener शांतपणे बंद पडू शकतो. लिंक्स रिडायरेक्ट होणे थांबते आणि कोणालाही याची माहिती मिळत नाही, कारण लिंकवर क्लिक करणारी व्यक्ती ती लिंक निकामी झाली आहे असे समजते. होम पेजऐवजी प्रत्यक्ष short URL वर uptime check सेट करा आणि रिडायरेक्शन व्यतिरिक्त इतर कोणत्याही प्रतिसादावर अलर्ट मिळवा. Uptime Kuma चे self-hosted instance हे काम उत्तम प्रकारे करते आणि ते विशिष्ट status code साठी मॉनिटर करू शकते.
कंटेनरचा बॅकअप घेण्याऐवजी डेटाबेसचा बॅकअप घ्या. एका कमांडद्वारे त्याचा डंप घेता येतो.
sudo docker compose exec -T database pg_dump -U shlink shlink | gzip > shlink-$(date +%F).sql.gzती फाईल आणि तुमची compose फाईल मिळून नवीन सर्व्हरवर संपूर्ण सेवा पुन्हा तयार करता येते. सर्व्हरवरील प्रत्येक अॅपसाठी अशा जोडीची आवश्यकता असते. फोटो लायब्ररीच्या बाबतीत हे थोडे क्लिष्ट असते, कारण PhotoPrism आणि Immich हे दोन्ही मूळ फोटो डिस्कवर साठवतात आणि डेटाबेसमध्ये त्यांच्या नोंदी ठेवतात, त्यामुळे केवळ डंपने काहीही रिस्टोर होत नाही. अपग्रेड करण्यासाठी आधी sudo docker compose pull आणि त्यानंतर sudo docker compose up -d वापरावे लागते. Shlink सुरू होताना सर्व नवीन migrations आपोआप कार्यान्वित करते. इमेज pull करण्यापूर्वी डंप घ्या, कारण एकदा झालेली migration पुन्हा मागे (rollback) घेता येत नाही.
FAQ
रिव्हर्स प्रॉक्सी जोडल्यानंतर माझ्या शॉर्ट लिंक्स 404 (404) एरर का देत आहेत?
Shlink हे Host हेडरमधील डोमेनशी शॉर्ट कोड जुळवते. जर प्रॉक्सीने स्वतःचे नाव किंवा अंतर्गत पत्ता पाठवला, तर Shlink त्या कोडला अशा डोमेनवर शोधते जिथे कोणतीही लिंक नसते, त्यामुळे ते 404 एरर देते. nginx लोकेशन ब्लॉक मध्ये proxy_set_header Host $host; सेट करा आणि प्रॉक्सी रीलोड करा. कंटेनर रीस्टार्ट न करता लिंक्स लगेच काम करू लागतील.
मला Postgres ची गरज आहे की SQLite पुरेसे आहे?
Shlink वापरून पाहण्यासाठी SQLite ठीक आहे आणि त्यासाठी दुसऱ्या कंटेनरची गरज नाही. महत्त्वाच्या लिंक्स प्रकाशित करण्यापूर्वी Postgres वर स्थलांतर करा, कारण प्रत्येक क्लिकसोबत व्हिजिटच्या ओळी वाढत जातात आणि SQLite रायट्स (writes) सीरियलाइज करते. नंतर स्विच करताना लिंक्स एक्सपोर्ट आणि पुन्हा इम्पोर्ट कराव्या लागतात, त्यामुळे सुरुवातीलाच Postgres निवडल्यास तुमचे हे स्थलांतर वाचते.
मी कॉपी करायला विसरलेली API की (API key) पुन्हा मिळवू शकतो का?
नाही. Shlink की चा हॅश स्टोअर करते, त्यामुळे api-key:list फक्त नावे आणि स्थिती दाखवते, पण की चे मूल्य कधीही दाखवत नाही. shlink api-key:generate वापरून नवीन की तयार करा, ती वेब क्लायंटमध्ये पेस्ट करा आणि त्यानंतर जुनी की shlink api-key:disable वापरून डिसेबल करा जेणेकरून ती काम करणे थांबवेल.
माझ्या व्हिजिट स्टॅट्समध्ये देशाचे कॉलम रिकामे का आहेत?
जियोलोकेशनसाठी GeoLite2 डेटाबेसची आवश्यकता असते, जो Shlink फक्त तेव्हाच डाउनलोड करते जेव्हा तुम्ही त्याला GEOLITE_LICENSE_KEY देता. ही की MaxMind कडून मोफत मिळते. ती एन्व्हायरनमेंट सेक्शनमध्ये जोडा, कंटेनर पुन्हा तयार करा आणि नवीन व्हिजिट्सचे लोकेशन शोधले जाईल. त्याआधी नोंदवलेल्या व्हिजिट्स रिकाम्याच राहतील, जोपर्यंत तुम्ही shlink visit:locate चालवत नाही.
मी Shlink दुसऱ्या सर्व्हरवर कसे हलवू?
डोमेन कायम ठेवा आणि डेटा हलवा. pg_dump वापरून डेटाबेसचा डंप घ्या, डंप आणि कंपोज फाईल नवीन सर्व्हरवर कॉपी करा, स्टॅक सुरू करा आणि प्रत्यक्ष ट्रॅफिक येण्यापूर्वी रिकाम्या डेटाबेसमध्ये डंप रिस्टोअर करा. DNS रेकॉर्ड सर्वात शेवटी बदला. शॉर्ट कोड्स आणि त्यांचा व्हिजिट इतिहास सुरक्षित राहतो, कारण सर्व काही डेटाबेसमध्ये असते.