Shlink کے ساتھ اپنا URL شارٹنر کیسے بنائیں
Docker Compose کا استعمال کرتے ہوئے VPS پر Shlink سیٹ اپ کریں۔ اس گائیڈ میں Postgres ڈیٹا بیس، HTTPS کنفیگریشن، API کیز اور کلک کے اعداد و شمار حاصل کرنے کا مکمل طریقہ موجود ہے۔
آپ کیا بنا رہے ہیں
خود سے میزبانی کردہ (self-hosted) URL شارٹنر ایک چھوٹا سرور ہے جو ایک طویل لنک کو آپ کی ملکیت والے مختصر لنک میں تبدیل کرتا ہے، اور اس پر ہونے والے ہر کلک کو شمار کرتا ہے۔ Shlink اس مقصد کے لیے بہترین انتخاب ہے: یہ اوپن سورس ہے، Docker امیج کے طور پر ریلیز ہوتا ہے، اور ایک کنٹینر اور ڈیٹا بیس کے ساتھ مکمل کام انجام دیتا ہے۔ یہ گائیڈ اسے ایک VPS پر، ایک حقیقی مختصر ڈومین کے پیچھے، HTTPS، API کی، QR کوڈز اور کلک کے اعداد و شمار کے ساتھ ترتیب دیتی ہے۔
دو اجزاء اسے ایک کمرشل شارٹنر جیسا بناتے ہیں۔ API سرور ری ڈائریکٹس (redirects) کا جواب دیتا ہے اور ڈیٹا کو محفوظ رکھتا ہے۔ ویب کلائنٹ ایک الگ سٹیٹک ایپ ہے جو آپ کے براؤزر سے اس API کے ساتھ رابطہ کرتی ہے۔ آپ دونوں کو چلا سکتے ہیں، یا صرف API کو چلا کر اسے کمانڈ لائن سے کنٹرول کر سکتے ہیں۔
یہاں دیے گئے ورژن نمبرز جولائی 2026 تک کے تازہ ترین ہیں: Shlink 5.1 اور shlink-web-client 4.8۔
مختصر ڈومین کو پہلے سرور کی طرف پوائنٹ کریں
ڈومین ہی پروڈکٹ ہے۔ s.example.com/abc123 وہ لنک ہے جسے لوگ دیکھتے ہیں، لہذا کچھ مختصر منتخب کریں اور کسی بھی چیز کو انسٹال کرنے سے پہلے اس کا انتخاب کریں۔ Shlink ہر مختصر URL کے ساتھ ڈومین کو محفوظ کرتا ہے، اور اسے بعد میں تبدیل کرنے کا مطلب یہ ہے کہ آپ کے پہلے سے دیے گئے تمام لنکس کام کرنا چھوڑ دیں گے۔
مختصر ڈومین کے لیے ایک DNS A ریکارڈ بنائیں، جو آپ کے VPS کے پبلک IPv4 ایڈریس کی طرف اشارہ کرے۔ اگر سرور میں IPv6 موجود ہے تو ایک AAAA ریکارڈ بھی شامل کریں۔ پھر آگے بڑھنے سے پہلے تصدیق کریں کہ یہ ریزولو (resolve) ہو رہا ہے۔
dig +short s.example.com Aآؤٹ پٹ آپ کے سرور کا ایڈریس ہونا چاہیے۔ اگر یہ خالی ہے، تو ریکارڈ ابھی تک پروپیگیٹ (propagate) نہیں ہوا ہے، اور بعد کا ہر مرحلہ الجھا دینے والے طریقے سے ناکام ہو جائے گا، کیونکہ TLS (transport layer security) سرٹیفکیٹ ایسے نام کے لیے جاری نہیں کیا جا سکتا جو ریزولو نہ ہوتا ہو۔
The compose file
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 لائن ایپ کو ایسے باکس پر بھی ظاہر کر دے گی جس کی فائر وال بند دکھائی دیتی ہے۔ لوپ بیک ایڈریس پر بائنڈ کرنا اس سے بچاتا ہے۔ یہی پیٹرن کسی بھی ایسی ایپ پر لاگو ہوتا ہے جسے آپ اس طرح چلاتے ہیں، اور اس کی مزید تفصیل VPS پر Docker Compose کے لیے گائیڈ میں موجود ہے۔
ڈیٹا بیس کا پاس ورڈ 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/healthایک 200 کا مطلب ہے کہ API زندہ ہے اور ڈیٹا بیس کنکشن کام کر رہا ہے۔ یہاں ایک 500 تقریباً ہمیشہ ڈیٹا بیس کی وجہ سے ہوتا ہے: .env میں موجود DB_PASSWORD اس سے میل نہیں کھاتا جس کے ساتھ Postgres بنایا گیا تھا، کیونکہ Postgres امیج POSTGRES_PASSWORD کو صرف تب پڑھتا ہے جب وہ ایک خالی ڈیٹا ڈائریکٹری کو انیشیالائز (initialise) کرتا ہے۔ پاس ورڈ کو بعد میں تبدیل کرنے کا کوئی اثر نہیں ہوتا جب تک کہ آپ والیوم کو ہٹا کر دوبارہ شروع نہ کریں۔
اس کے آگے HTTPS کو ختم کریں
Shlink پورٹ 8080 پر سادہ HTTP فراہم کرتا ہے۔ TLS کا کام ریورس پراکسی کا ہے، اور سب سے اہم سیٹنگ اصل ہوسٹ نام کو آگے بھیجنا ہے۔ Shlink یہ فیصلہ کرنے کے لیے کہ شارٹ کوڈ کس ڈومین سے تعلق رکھتا ہے، Host ہیڈر کو پڑھتا ہے، لہذا ایسی پراکسی جو اسے دوبارہ لکھتی ہے، موجودہ لنکس پر 404 رسپانس دیتی ہے، اور وزٹ کے اعدادوشمار غلط ڈومین سے منسلک ہو جاتے ہیں۔
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;
}
}اس کے بعد سرٹیفکیٹ جاری کریں۔ مکمل طریقہ کار، بشمول تجدید کا ٹائمر، Ubuntu 24.04 پر nginx کے لیے Certbot گائیڈ میں موجود ہے۔
sudo certbot --nginx -d s.example.comcompose فائل میں IS_HTTPS_ENABLED: "true" وہ چیز ہے جو Shlink کو اس کے واپس کردہ شارٹ URLs میں https:// پرنٹ کرنے پر مجبور کرتی ہے۔ یہ بذات خود TLS کو فعال نہیں کرتا ہے۔ اسے HTTPS پراکسی کے پیچھے false چھوڑ دیں، ورنہ API کی طرف سے واپس کیا گیا ہر لنک ایک http:// لنک ہوگا جو پھر ری ڈائریکٹ ہوتا ہے، جس سے ایک اضافی راؤنڈ ٹرپ ضائع ہوتا ہے اور ویب کلائنٹ میں یہ غلط دکھائی دیتا ہے۔
API key تخلیق کریں
کسی بھی چیز کے لیے API کے ساتھ رابطہ کرنے کی خاطر ایک key کا ہونا ضروری ہے۔ کنٹینر کے اندر CLI کے ذریعے ایک key تیار کریں۔
sudo docker compose exec shlink shlink api-key:generate --name "web client"یہ کمانڈ key کو صرف ایک بار پرنٹ کرتی ہے۔ اسے ابھی کاپی کر لیں، کیونکہ یہ ہیش (hashed) حالت میں محفوظ ہوتی ہے اور دوبارہ نہیں دکھائی جا سکتی۔ shlink api-key:list ہر key کا نام اور اس کی فعالیت کی حیثیت دکھاتا ہے، لیکن خود key کبھی نہیں دکھاتا۔ کسی key کو منسوخ کرنے کے لیے shlink api-key:disable اور اس کا نام استعمال کریں۔
ہر REST کال میں key کو X-Api-Key ہیڈر میں شامل کیا جاتا ہے۔
curl -H "X-Api-Key: YOUR_KEY" https://s.example.com/rest/v3/short-urlsایک JSON آبجیکٹ جس میں shortUrls key موجود ہو، اس کا مطلب ہے کہ key درست کام کر رہی ہے۔ 401 جس میں INVALID_API_KEY کا پیغام ہو، اس کا مطلب ہے کہ key غلط ہے، غیر فعال ہے، یا اس کی میعاد ختم ہو چکی ہے۔
کمانڈ لائن سے مختصر لنکس بنانا
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) اور یوزر ایجنٹ شامل ہوتے ہیں۔ ملک اور شہر کے کالم خالی رہتے ہیں جب تک کہ آپ GEOLITE_LICENSE_KEY انوائرمنٹ ویری ایبل سیٹ نہ کریں۔ یہ ایک مفت MaxMind کی (key) ہے جسے Shlink، GeoLite2 ڈیٹا بیس ڈاؤن لوڈ کرنے کے لیے استعمال کرتا ہے۔ اس کے بغیر، وزٹس ریکارڈ تو ہوتے ہیں، لیکن ان کا محل وقوع ظاہر نہیں ہوتا۔
ویب کلائنٹ اور QR کوڈز
ویب کلائنٹ اب 127.0.0.1:8081 پر موجود ہے اور اسے اپنی پراکسی انٹری درکار ہے، یا اگر آپ اسے پبلش نہیں کرنا چاہتے تو SSH ٹنل استعمال کریں۔ پہلی بار لوڈ ہونے پر یہ سرور URL اور API کی (key) مانگتا ہے۔ https://s.example.com اور وہ کی (key) درج کریں جو آپ نے جنریٹ کی ہے۔ کلائنٹ دونوں کو براؤزر اسٹوریج میں محفوظ رکھتا ہے اور براہ راست آپ کی API کو کال کرتا ہے، لہذا کوئی ڈیٹا کسی اور کے پاس نہیں جاتا۔
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 پر اپ ٹائم چیک لگائیں، اور کسی بھی ایسی چیز پر الرٹ سیٹ کریں جو ری ڈائریکٹ نہ ہو۔ ایک سیلف ہوسٹڈ Uptime Kuma انسٹینس یہ کام بخوبی انجام دیتا ہے، اور یہ ایک مخصوص اسٹیٹس کوڈ کی نگرانی کر سکتا ہے۔
کنٹینر کا نہیں، ڈیٹا بیس کا بیک اپ لیں۔ ایک کمانڈ اسے ڈمپ کر دیتی ہے۔
sudo docker compose exec -T database pg_dump -U shlink shlink | gzip > shlink-$(date +%F).sql.gzوہ فائل اور آپ کی compose فائل مل کر نئے سرور پر پوری سروس کو دوبارہ تعمیر کر دیتی ہیں۔ اپ گریڈز sudo docker compose pull کے بعد sudo docker compose up -d کے ذریعے کیے جاتے ہیں، اور Shlink شروع ہوتے ہی کوئی بھی نئی مائیگریشنز چلا دیتا ہے۔ پل (pull) کرنے سے پہلے ڈمپ لے لیں، کیونکہ مائیگریشن کو رول بیک نہیں کیا جا سکتا۔
FAQ
ریورس پراکسی شامل کرنے کے بعد میرے شارٹ لنکس 404 کیوں دیتے ہیں؟
Shlink شارٹ کوڈ کو Host ہیڈر میں موجود ڈومین کے ساتھ ملاتا ہے۔ اگر کوئی پراکسی اپنا نام یا اندرونی ایڈریس بھیجتی ہے، تو Shlink اس کوڈ کو ایسی ڈومین کے تحت تلاش کرتا ہے جس میں کوئی لنکس نہیں ہوتے، اس لیے وہ 404 کا جواب دیتا ہے۔ nginx لوکیشن بلاک میں proxy_set_header Host $host; سیٹ کریں اور پراکسی کو ری لوڈ کریں۔ لنکس فوری طور پر کام کرنا شروع کر دیں گے، اور کنٹینر کو ری اسٹارٹ کرنے کی ضرورت نہیں پڑے گی۔
کیا مجھے Postgres کی ضرورت ہے، یا SQLite کافی ہے؟
SQLite Shlink کو آزمانے کے لیے ٹھیک ہے اور اس کے لیے کسی دوسرے کنٹینر کی ضرورت نہیں ہے۔ اہم لنکس شائع کرنے سے پہلے Postgres پر منتقل ہو جائیں، کیونکہ ہر کلک کے ساتھ وزٹ کی قطاریں بڑھتی ہیں اور SQLite رائٹس (writes) کو سیریلائز کرتا ہے۔ بعد میں سوئچ کرنے کا مطلب ہے اپنے لنکس کو ایکسپورٹ اور دوبارہ امپورٹ کرنا، اس لیے شروع میں ہی Postgres کا انتخاب آپ کو اس مائیگریشن سے بچا لیتا ہے۔
کیا میں وہ 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 کے ساتھ ڈیٹا بیس کا ڈمپ لیں، ڈمپ اور compose فائل کو نئے سرور پر کاپی کریں، اسٹیک کو اسٹارٹ کریں، اور پھر اصلی ٹریفک آنے سے پہلے خالی ڈیٹا بیس میں ڈمپ کو ریسٹور کریں۔ DNS ریکارڈ کو سب سے آخر میں تبدیل کریں۔ شارٹ کوڈز اور ان کی وزٹ ہسٹری محفوظ رہتی ہے، کیونکہ سب کچھ ڈیٹا بیس میں موجود ہوتا ہے۔