Ubuntu VPS-এ FreshRSS ইনস্টল করার নিয়ম
Ubuntu 24.04 সার্ভারে Apache, PHP 8.3 এবং MariaDB ব্যবহার করে FreshRSS সেটআপ করুন। এই গাইডে ভার্চুয়াল হোস্ট কনফিগারেশন, cron job এবং মোবাইল API ব্যবহারের সঠিক পদ্ধতি দেওয়া হলো।
আপনি যা তৈরি করছেন
একটি সেলফ-হোস্টেড RSS রিডার হলো এমন একটি ফিড রিডার যা আপনার নিজস্ব সার্ভারে চলে, তাই কেউ এটি বন্ধ করতে বা আপনার প্রদর্শিত বিষয়বস্তু পরিবর্তন করতে পারে না। এই নির্দেশিকাটি Ubuntu 24.04 VPS-এ FreshRSS স্থাপন করবে: সামনে Apache, পেছনে PHP, স্টোরেজের জন্য MariaDB এবং নতুন আর্টিকেল সংগ্রহ করার জন্য একটি cron job। RSS (really simple syndication) হলো এমন একটি ফাইল ফরম্যাট যা একটি সাইট প্রকাশ করে, যাতে সফটওয়্যার তার আর্টিকেলগুলো পড়তে পারে। FreshRSS হলো সেই PHP অ্যাপ্লিকেশন যা এই ফাইলগুলো সংগ্রহ করে, আর্টিকেলগুলো সংরক্ষণ করে এবং আপনাকে একটি ওয়েব ইন্টারফেসের পাশাপাশি একটি API (application programming interface) প্রদান করে, যা ফোনের অ্যাপগুলো ব্যবহার করতে পারে।
ইনস্টলেশন প্রক্রিয়াটি ছোট: একটি রিলিজ আনপ্যাক করা, একটি ডাটাবেস তৈরি করা, একটি ভার্চুয়াল হোস্ট লেখা এবং একটি কমান্ড লাইন ইনস্টলার চালানো। নিচে বর্ণিত কাজের বেশিরভাগ অংশই হলো সেই বিষয়গুলো যা মানুষ পরে ভুল করে, যেমন রিফ্রেশ জব, মোবাইল API-এর জন্য এনকোড করা স্ল্যাশ এবং ফাইলের মালিকানা।
জুলাই 2026 অনুযায়ী FreshRSS 1.29.1 হলো বর্তমান রিলিজ এবং এর জন্য PHP 8.1 বা তার পরবর্তী সংস্করণ প্রয়োজন। Ubuntu 24.04-এ PHP 8.3 থাকে, তাই ডিস্ট্রিবিউশন প্যাকেজগুলোই যথেষ্ট এবং আপনার কোনো থার্ড পার্টি PHP রিপোজিটরির প্রয়োজন নেই।
একটি কার্যকর LAMP স্ট্যাক থেকে শুরু করুন
FreshRSS একটি সাধারণ PHP অ্যাপ্লিকেশন, তাই অন্য যেকোনো অ্যাপ্লিকেশনের মতোই এর জন্য একই ভিত্তি প্রয়োজন। আপনি যদি এখনও সেই ভিত্তি তৈরি না করে থাকেন, তবে প্রথমে Ubuntu 24.04-এ LAMP স্ট্যাক সেটআপ অনুসরণ করুন এবং তারপর এখানে ফিরে আসুন। সংক্ষিপ্ত সংস্করণটি হলো:
sudo apt update
sudo apt install -y apache2 mariadb-server php libapache2-mod-php
sudo systemctl enable --now apache2 mariadbsystemctl status apache2 কমান্ডটি active (running) রিপোর্ট করা উচিত। যদি Apache চালু না হয়, তবে সাধারণত অন্য কোনো প্রসেস ইতিমধ্যে পোর্ট 80 দখল করে রাখে এবং sudo ss -ltnp | grep :80 কমান্ডটি সেই প্রসেসের নাম জানিয়ে দেয়।
FreshRSS-এর জন্য প্রয়োজনীয় PHP এক্সটেনশনসমূহ
FreshRSS-এর জন্য libxml, cURL, JSON, PDO_MySQL, PCRE এবং ctype অপরিহার্য। এছাড়াও এটি mbstring, iconv, Zlib, ZipArchive এবং 32-বিট সিস্টেমের ক্ষেত্রে GMP সমর্থন আশা করে। Ubuntu-তে এগুলো ডিস্ট্রিবিউশন প্যাকেজ হিসেবে পাওয়া যায়:
sudo apt install -y php-curl php-mbstring php-xml php-zip php-mysql php-intl php-gmp
sudo systemctl restart apache2php -m ব্যবহার করে PHP বর্তমানে কী কী লোড করেছে তা যাচাই করুন। কোনো এক্সটেনশন অনুপস্থিত থাকলে তা ইনস্টলার শুরু হওয়া আটকায় না। এটি ইনস্টলারের রিকোয়ারমেন্ট স্ক্রিনে একটি লাল রঙের লাইনের মাধ্যমে এক্সটেনশনটির নাম প্রদর্শন করে, যা সমস্যার কারণ খুঁজে বের করার জন্য বিভ্রান্তিকর হতে পারে। তাই এখনই নিশ্চিত হয়ে নিন। Apache রিস্টার্ট করা জরুরি, কারণ libapache2-mod-php PHP-কে Apache প্রসেসের ভেতরেই রাখে। ফলে নতুন ইনস্টল করা কোনো এক্সটেনশন রিস্টার্ট না করা পর্যন্ত ওয়েব সার্ভারের কাছে অদৃশ্য থাকে।
রিলিজ ডাউনলোড করুন
FreshRSS-কে ডিফল্ট ওয়েব রুটের বাইরে ইনস্টল করুন এবং Apache-কে সেটির দিকে নির্দেশ করুন। অ্যাপ্লিকেশন ডিরেক্টরিকে ডকুমেন্ট রুট থেকে আলাদা রাখলে শুধুমাত্র public ফোল্ডারটিই HTTP-এর মাধ্যমে অ্যাক্সেসযোগ্য থাকে।
cd /tmp
curl -fsSLO https://github.com/FreshRSS/FreshRSS/archive/refs/tags/1.29.1.tar.gz
tar xzf 1.29.1.tar.gz
sudo mv FreshRSS-1.29.1 /srv/freshrssএখন পারমিশন বা অনুমতির বিষয়টি, যার ব্যাপারে FreshRSS ডকুমেন্টেশন অত্যন্ত কঠোর: ওয়েব সার্ভার ব্যবহারকারীর পুরো ডিরেক্টরি ট্রি-এর মালিকানা থাকা উচিত, গ্রুপ প্রতিটি ফাইল পড়তে পারবে এবং গ্রুপ ./data/-এ লিখতে পারবে।
sudo chown -R www-data:www-data /srv/freshrss
sudo chmod -R g+r /srv/freshrss
sudo chmod -R g+w /srv/freshrss/dataএটি এড়িয়ে গেলে ইনস্টলার তার কনফিগারেশন লেখার সময় ব্যর্থ হবে, কারণ PHP www-data হিসেবে চলে এবং www-data রুট (root)-এর মালিকানাধীন কোনো ডিরেক্টরিতে লিখতে পারে না।
ডেটাবেস তৈরি করুন
FreshRSS-এ SQLite, MariaDB, MySQL এবং PostgreSQL সমর্থিত। SQLite-এর জন্য কোনো সেটআপের প্রয়োজন হয় না এবং একজন ব্যবহারকারীর কয়েকশ ফিডের জন্য এটি যথেষ্ট। যখন একাধিক ব্যবহারকারী একই ইনস্ট্যান্স ব্যবহার করেন, তখন MariaDB ভালো পছন্দ। কারণ সেক্ষেত্রে রিফ্রেশ জব এবং ওয়েব ইন্টারফেস থেকে আসা কনকারেন্ট রাইটগুলো একটি সিঙ্গেল ফাইল লকের জন্য আর প্রতিদ্বন্দ্বিতা করে না।
sudo mariadb -e "CREATE DATABASE freshrss CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mariadb -e "CREATE USER 'freshrss'@'localhost' IDENTIFIED BY 'ReplaceThisPassword';"
sudo mariadb -e "GRANT ALL PRIVILEGES ON freshrss.* TO 'freshrss'@'localhost';"
sudo mariadb -e "FLUSH PRIVILEGES;"utf8mb4 ব্যবহার করুন, utf8 নয়। ফিডগুলোতে ইমোজি এবং নন-ল্যাটিন স্ক্রিপ্ট থাকে, আর পুরনো তিন বাইটের utf8 এনকোডিং প্রথম চার বাইটের ক্যারেক্টারেই আর্টিকেলের শিরোনাম কেটে ফেলে।
Apache ভার্চুয়াল হোস্ট
পাবলিক ডিরেক্টরি হলো p/, গাছের মূল অংশ নয়। আপনার ডাটাবেস পাসওয়ার্ড ধারণকারী কনফিগারেশন ফাইলসহ অন্য সবকিছু ডকুমেন্ট রুটের উপরে থাকে, যেখান থেকে Apache কখনোই কোনো ফাইল পরিবেশন করবে না।
<VirtualHost *:80>
ServerName rss.example.com
DocumentRoot /srv/freshrss/p/
<Directory /srv/freshrss/p>
AllowOverride AuthConfig FileInfo Indexes Limit
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/freshrss_error.log
CustomLog ${APACHE_LOG_DIR}/freshrss_access.log combined
AllowEncodedSlashes On
</VirtualHost>এটিকে /etc/apache2/sites-available/freshrss.conf হিসেবে সেভ করুন এবং এটি সক্রিয় করুন:
sudo a2enmod rewrite
sudo a2ensite freshrss
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2configtest এর আউটপুট Syntax OK হওয়া উচিত। AllowEncodedSlashes On কে ঐচ্ছিক মনে হতে পারে কিন্তু এটি তা নয়: Google Reader API এমন ফিড আইডেন্টিফায়ার পাঠায় যাতে %2F থাকে, এবং এই ডিরেক্টিভ ছাড়া Apache সেগুলোকে প্রত্যাখ্যান করে। ফলে ওয়েব ইন্টারফেস সঠিকভাবে কাজ করলেও মোবাইল অ্যাপগুলো সিঙ্ক হতে ব্যর্থ হয়।
লগ ইন করার আগে HTTPS যোগ করুন
আপনি এই সাইটে একটি পাসওয়ার্ড টাইপ করতে যাচ্ছেন, তাই প্রথমে একটি সার্টিফিকেট সংগ্রহ করুন। সার্ভারের দিকে একটি A রেকর্ড পয়েন্ট করুন, তারপর Ubuntu-তে Apache-এর জন্য Certbot সেটআপ অনুসরণ করুন এবং sudo certbot --apache -d rss.example.com কমান্ডটি চালান। Certbot পোর্ট 443-এর জন্য ভার্চুয়াল হোস্টটিকে নতুন করে লেখে এবং রিডাইরেক্ট যোগ করে। curl -I https://rss.example.com/ দিয়ে নিশ্চিত করুন, যা থেকে একটি 200 অথবা লগ ইন পেজে রিডাইরেক্ট আসার কথা।
কমান্ড লাইন থেকে ইনস্টলার চালান
FreshRSS-এ একটি ব্রাউজার-ভিত্তিক ইনস্টলার রয়েছে, তবে কমান্ড লাইন সংস্করণটি বারবার ব্যবহার করা যায় এবং আপনি ঠিক কী নির্বাচন করেছেন তার একটি রেকর্ড থেকে যায়।
sudo -u www-data php /srv/freshrss/cli/do-install.php \
--default-user admin --auth-type form --environment production \
--base-url https://rss.example.com --language en --api-enabled \
--db-type mysql --db-host localhost --db-user freshrss \
--db-password 'ReplaceThisPassword' --db-base freshrss
sudo -u www-data php /srv/freshrss/cli/create-user.php \
--user admin --password 'a-long-passphrase' --api-password 'a-different-passphrase'উভয় কমান্ডই www-data হিসেবে চালান। root হিসেবে এগুলো চালালে কনফিগারেশন ফাইলগুলোর মালিকানা root-এর কাছে চলে যায়, যার ফলে পরবর্তীতে ওয়েব ইন্টারফেস কোনো সেটিংস সংরক্ষণ করতে ব্যর্থ হয়। --environment production-ও গুরুত্বপূর্ণ, কারণ ডেভেলপমেন্ট সেটিংটি PHP নোটিশগুলোকে সরাসরি পেজে প্রদর্শন করে।
https://rss.example.com/ লোড করুন এবং admin হিসেবে লগ ইন করুন।
ফিডগুলো কেন নিজে থেকে রিফ্রেশ হয় না
আপনি যতক্ষণ না নির্দেশ দিচ্ছেন, ততক্ষণ পর্যন্ত কোনো কিছুই আপনার ফিডগুলো পোল (poll) করে না। FreshRSS কেবল তখনই রিফ্রেশ হয় যখন ব্রাউজারে এটি খোলা থাকে; এর মানে হলো, আপনি দিনে দুবার ভিজিট করলে আপনার ফিডগুলো বারো ঘণ্টা পুরনো আর্টিকেল দেখাবে। এর সমাধান হলো প্রজেক্টের সাথে আসা app/actualize_script.php স্ক্রিপ্টটি ব্যবহার করা, যা cron থেকে চালাতে হয়।
sudo crontab -u www-data -eনিচের লাইনটি যোগ করুন:
*/20 * * * * php /srv/freshrss/app/actualize_script.php > /tmp/FreshRSS.log 2>&1বিশ মিনিট হলো একটি যৌক্তিক সময়সীমা, কারণ এই স্ক্রিপ্টটি প্রতি বিশ মিনিটের কম সময়ের ব্যবধানে কোনো ফিড রিফ্রেশ করে না। তাই এর চেয়ে ঘন ঘন শিডিউল করলে কেবল CPU-এর ওপর চাপ বাড়বে। প্রথমে একবার ম্যানুয়ালি চালিয়ে দেখুন:
sudo -u www-data php /srv/freshrss/app/actualize_script.phpসফলভাবে সম্পন্ন হলে আউটপুটে প্রতিটি ফিডের নাম দেখাবে এবং কোনো PHP এরর ছাড়াই শেষ হবে। যদি কোনো আউটপুট না আসে, তবে বুঝতে হবে cron ইউজার ভুল আছে। আর data/-এ পারমিশন এরর দেখালে বুঝতে হবে chmod -R g+w ধাপটি বাদ পড়েছে।
আপনার প্রথম ফিডগুলো যোগ করুন
ইন্টারফেসের উপরের বাম দিকে থাকা প্লাস বোতামটি ব্যবহার করুন, একটি সাইটের ঠিকানা পেস্ট করুন, এবং FreshRSS আপনার জন্য ফিডের লিঙ্কটি খুঁজে বের করবে। বেশিরভাগ সাইট তাদের ফিডের কথা প্রচার না করলেও সেগুলো প্রকাশ করে, যা সাধারণত /feed, /rss অথবা /atom.xml ঠিকানায় থাকে। ক্যাটাগরিগুলো হলো ফোল্ডার, এবং সেগুলোর মধ্যে একটি ফিড সরানো খুবই সহজ।
অন্য কোনো রিডার থেকে এখানে আসতে চাইলে, সেখান থেকে একটি OPML ফাইল এক্সপোর্ট করুন এবং সাবস্ক্রিপশন ম্যানেজমেন্ট পেজের অধীনে সেটি ইমপোর্ট করুন। OPML (outline processor markup language) হলো ফিড তালিকার স্ট্যান্ডার্ড ফরম্যাট, এবং যে কোনো ভালো রিডার এটি সাপোর্ট করে। বড় আকারের ইমপোর্ট প্রথমবার রিফ্রেশ করার সময় ধীরগতির হতে পারে কারণ প্রতিটি ফিড একবার করে ফেচ করা হয়, তাই গতির বিচার করার আগে প্রথম cron রান সম্পন্ন হওয়ার জন্য সময় দিন।
আপনার ফোনে পড়ুন
FreshRSS, Google Reader API সমর্থন করে, যা প্রায় সব RSS অ্যাপেই কাজ করে। এক্ষেত্রে দুটি বিষয় নিশ্চিত করতে হবে। অথেন্টিকেশন সেটিংসে "Allow API access" অপশনটি চালু থাকতে হবে, যা উপরের --api-enabled ফ্ল্যাগটি ইতিমধ্যে সেট করেছে। আপনার প্রোফাইলের অধীনে, API password ফিল্ডে একটি মান থাকতে হবে। এটি আপনার লগইন পাসওয়ার্ড থেকে আলাদা রাখা হয়েছে, কারণ ফোন হারিয়ে যাওয়ার ঝুঁকি বেশি থাকে।
https://rss.example.com/api/ ভিজিট করুন এবং "Check full server configuration" নির্বাচন করুন। একটি সঠিক সেটআপে PASS ফলাফল দেখাবে। এখানে কোনো সমস্যা হলে তার কারণ সাধারণত AllowEncodedSlashes On লাইনটি অনুপস্থিত থাকা। অ্যাপে, সার্ভারের ঠিকানা হিসেবে https://rss.example.com/api/greader.php, ইউজারনেম হিসেবে আপনার FreshRSS ইউজার এবং পাসওয়ার্ড হিসেবে API password প্রদান করুন।
Docker-এর বিকল্প
আপনি যদি নিজে থেকে PHP এবং Apache রক্ষণাবেক্ষণ করতে না চান, তবে এই প্রজেক্টটি একটি অফিসিয়াল freshrss/freshrss ইমেজ প্রকাশ করে। একটি compose ফাইল ব্যবহার করে আপনি অ্যাপ্লিকেশন এবং এর ডেটাবেস একসাথে পেতে পারেন। এর বিনিময়ে আপনাকে প্রচলিত কিছু বিষয় মেনে নিতে হবে: হোস্ট মেশিনে কম উপাদান থাকবে, কিন্তু কোনো সমস্যা হলে ডিবাগ করার জন্য একটি অতিরিক্ত স্তর থাকবে এবং TLS (transport layer security)-এর জন্য একটি রিভার্স প্রক্সি প্রয়োজন হবে। যদি এটি আপনার জন্য সুবিধাজনক হয়, তবে VPS-এর জন্য Docker Compose-এর মৌলিক বিষয়সমূহ-এ ফাইলের ফরম্যাট সম্পর্কে আলোচনা করা হয়েছে এবং cron লাইনটি হবে docker exec --user www-data freshrss php ./app/actualize_script.php।
ব্যাকআপ এবং আপগ্রেড
আপনার সার্ভারের অবস্থা দুটি জিনিসের ওপর নির্ভর করে: ডেটাবেস এবং /srv/freshrss/data/। sudo mysqldump freshrss > freshrss.sql ব্যবহার করে প্রথমটির একটি ডাম্প নিন, দ্বিতীয়টি কপি করুন এবং উভয়ই এই সার্ভারের বাইরে অন্য কোথাও সংরক্ষণ করুন। আপনার সাবস্ক্রিপশন তালিকার একটি OPML এক্সপোর্ট মাঝে মাঝে রাখা ভালো, কারণ এই ফাইলটি যেকোনো RSS সফটওয়্যারে আপনার রিডিং সেটআপ পুনরায় তৈরি করতে পারে।
আপগ্রেড করার অর্থ হলো একই ডিরেক্টরিতে নতুন রিলিজটি আনপ্যাক করা এবং মালিকানা সংক্রান্ত কমান্ডগুলো পুনরায় চালানো। পরবর্তী পেজ লোড হওয়ার সময় FreshRSS স্বয়ংক্রিয়ভাবে তার ডেটাবেস মাইগ্রেশন সম্পন্ন করে। আপগ্রেড করার আগে অবশ্যই ব্যাকআপ নিন, কারণ ডেটাবেস মাইগ্রেশন ব্যর্থ হলে এবং তা পুনরুদ্ধার করতে না পারলে সেটি একটি অপূরণীয় পরিস্থিতি তৈরি করবে। একটি রিডার সার্ভিস চালানো কম ঝুঁকিপূর্ণ এবং আপনি যদি সেলফ-হোস্টিংয়ের যোগ্য বিষয়গুলোর তালিকা নিয়ে কাজ করেন, তবে এটি আপনার জন্য একটি ভালো প্রাথমিক প্রজেক্ট হতে পারে।
FAQ
আমার ফিডগুলো শুধুমাত্র FreshRSS খুললেই কেন আপডেট হয়?
কারণ আপনি কোনো শিডিউলার তৈরি না করা পর্যন্ত তা কাজ করে না। ব্রাউজার সেশন খোলা থাকলে FreshRSS ফিড রিফ্রেশ করে, কিন্তু ট্যাব বন্ধ থাকলে এটি কোনো কাজ করে না। www-data ব্যবহারকারী হিসেবে app/actualize_script.php কল করে ক্রন লাইনটি যোগ করুন, তারপর স্ক্রিপ্টটি একবার ম্যানুয়ালি চালিয়ে এর আউটপুট দেখুন। সাধারণত কোনো আউটপুট না আসা মানে হলো ক্রন ভুল ব্যবহারকারীর অধীনে চলছে, যার ফলে PHP data/-এ লিখতে পারছে না।
আমার মোবাইল অ্যাপ সংযোগ করতে পারছে না, কিন্তু ওয়েবসাইট কাজ করছে। কেন?
Google Reader API রিকোয়েস্ট পাথের ভেতরে এনকোড করা স্ল্যাশ (%2F) ব্যবহার করে, যা Apache ডিফল্টভাবে প্রত্যাখ্যান করে। ভার্চুয়াল হোস্টের ভেতরে AllowEncodedSlashes On যোগ করুন এবং Apache রিলোড করুন। https://rss.example.com/api/ খুলে "Check full server configuration" রান করে সমাধানটি নিশ্চিত করুন, যা PASS রিপোর্ট করবে। এছাড়া আপনার প্রোফাইলে API পাসওয়ার্ড সেট করা আছে কি না তা যাচাই করুন, কারণ এটি আপনার লগইন পাসওয়ার্ড থেকে আলাদা।
আমার কি SQLite নাকি MariaDB ব্যবহার করা উচিত?
একজন ব্যবহারকারীর জন্য SQLite ব্যবহার করুন, কারণ এতে আলাদা কিছু ইনস্টল করতে হয় না এবং কোনো পাসওয়ার্ড ম্যানেজ করার প্রয়োজন নেই। যখন একাধিক ব্যক্তি ইনস্ট্যান্সটি ব্যবহার করবেন অথবা কয়েকশ ফিডের বেশি হয়ে যাবে, তখন MariaDB ব্যবহার করুন। কারণ রিফ্রেশ জব এবং ওয়েব ইন্টারফেস একই সময়ে ডেটা লেখে এবং একটি সিঙ্গেল ফাইল লক তখন সীমাবদ্ধতা তৈরি করে। পরবর্তীতে এক্সপোর্ট এবং ইমপোর্ট কমান্ডের মাধ্যমে এদের মধ্যে পরিবর্তন করা সম্ভব, তাই এটি কোনো স্থায়ী সিদ্ধান্ত নয়।
কনফিগারেশন লেখার সময় ইনস্টলার ব্যর্থ হয়। সমস্যা কী?
Apache-এর অধীনে PHP www-data হিসেবে চলে এবং সেই ব্যবহারকারী root-এর মালিকানাধীন ডিরেক্টরিতে লিখতে পারে না। sudo chown -R www-data:www-data /srv/freshrss এবং sudo chmod -R g+w /srv/freshrss/data পুনরায় রান করুন, তারপর ইনস্টলারটি আবার শুরু করুন। যদি আপনি ইতিমধ্যে root হিসেবে কমান্ড লাইন ইনস্টলার চালিয়ে থাকেন, তবে পুনরায় চেষ্টা করার আগে data/-এর অধীনে তৈরি হওয়া ফাইলগুলো মুছে ফেলুন, কারণ সেগুলোর মালিকানাই মূল সমস্যা।
একটি সেলফ-হোস্টেড RSS রিডারের জন্য কেমন সার্ভার প্রয়োজন?
খুব সামান্য। ছোট প্ল্যানে কয়েকশ ফিড অনায়াসেই চালানো যায়, কারণ লোড বলতে প্রতি বিশ মিনিটে অল্প সময়ের জন্য HTTP ফেচিং হয় এবং পুরনো আর্টিকেল মুছে ফেললে ডেটাবেস ছোট থাকে। রিটেনশন পলিসির ওপর ভিত্তি করে ডিস্কের ব্যবহার বাড়ে, তাই সবকিছু চিরকাল জমা না রেখে আর্কাইভিং সেটিংসে একটি আর্টিকেল পার্জ পলিসি সেট করুন।