Ubuntu 24.04-এ সেলফ-হোস্টেড GitHub Actions রানার সেটআপ
Ubuntu 24.04-এ সেলফ-হোস্টেড GitHub Actions রানার সেটআপ করার পূর্ণাঙ্গ গাইড। এতে ডেডিকেটেড ইউজার তৈরি, checksum যাচাই, config.sh কনফিগারেশন এবং systemd সার্ভিস তৈরির নিয়ম রয়েছে।
সেলফ-হোস্টেড GitHub Actions রানার কী কাজ করে
সেলফ-হোস্টেড GitHub Actions রানার হলো এমন একটি প্রোগ্রাম যা আপনি আপনার নিজস্ব VPS-এ ইনস্টল করেন। এটি GitHub-এর কাছে কাজের (jobs) জন্য অনুরোধ পাঠায় এবং আপনার হার্ডওয়্যারে সেগুলো সম্পন্ন করে। আপনি এটিকে একটি রিপোজিটরির সাথে রেজিস্টার করেন এবং systemd সার্ভিস হিসেবে ইনস্টল করেন, ফলে প্রতিটি রিবুটের পর এটি স্বয়ংক্রিয়ভাবে চালু হয়। GitHub কাজের সময়সূচী নির্ধারণ করে এবং আপনার সার্ভার সেই কাজগুলো সম্পাদন করে।
আপনার নিজস্ব সার্ভারে CI (কন্টিনিউয়াস ইন্টিগ্রেশন) ব্যবহার করার দুটি সুবিধা রয়েছে। প্রথমত, বিল্ড মিনিট আর গণনা করা হয় না। দ্বিতীয়ত, একটি জব এমন সব রিসোর্সে পৌঁছাতে পারে যা শুধুমাত্র আপনার মেশিনের কাছেই আছে, যেমন ওয়ার্ম বিল্ড ক্যাশ বা প্রাইভেট নেটওয়ার্ক। এর বিনিময়ে আপনাকে নিরাপত্তার বিষয়টি মাথায় রাখতে হবে। রানার আপনার দেওয়া ইউজার হিসেবে workflow ফাইলে যা লেখা থাকে তা-ই কার্যকর করে, তাই ডিজাইন অনুযায়ী একটি workflow ফাইল মূলত রিমোট কোড এক্সিকিউশন। একটি প্রাইভেট রিপোজিটরিতে এটি নিরাপদ, কারণ শুধুমাত্র আপনার বিশ্বস্ত ব্যক্তিরাই সেখানে ফাইল যোগ করতে পারেন। পাবলিক রিপোজিটরিতে এটি একটি বড় ঝুঁকি, এবং fork pull requests সংক্রান্ত সেকশনে এর কার্যপদ্ধতি ব্যাখ্যা করা হয়েছে।
নিচের সবকিছু Ubuntu 24.04 এবং রানার ভার্সন 2.336.0-এর ওপর ভিত্তি করে লেখা, যা জুলাই 2026 অনুযায়ী বর্তমান রিলিজ।
শুরু করার আগে আপনার যা প্রয়োজন
একটি VPS থেকে শুরু করুন যেখানে একটি সাধারণ অ্যাডমিন অ্যাকাউন্ট এবং sudo সুবিধা রয়েছে, যা আপনি একটি নতুন VPS-এ প্রথম দশ মিনিট-এর মাধ্যমে অর্জন করেন। আপনাকে কোনো ইনবাউন্ড পোর্ট খোলার প্রয়োজন নেই। রানার GitHub-এর সাথে একটি আউটবাউন্ড HTTPS (hypertext transfer protocol secure) সংযোগ খোলে এবং কাজের অপেক্ষায় থাকার সময় তা খোলা রাখে, তাই GitHub কখনোই সরাসরি আপনার সার্ভারের সাথে সংযোগ স্থাপন করে না। আপনার ফায়ারওয়াল বাইরের জগতের জন্য বন্ধ থাকলেও কাজগুলো সার্ভারে পৌঁছাবে।
আপনার রিপোজিটরিতে অ্যাডমিন অধিকারও থাকা প্রয়োজন, কারণ রেজিস্ট্রেশন টোকেনটি রিপোজিটরির সেটিংসে প্রদর্শিত হয়।
রানারের জন্য একটি ডেডিকেটেড ইউজার তৈরি করুন
কখনও root হিসেবে বা আপনার নিজস্ব অ্যাডমিন ইউজার হিসেবে রানার চালাবেন না। প্রতিটি জব রানার ইউজারের অধিকার উত্তরাধিকারসূত্রে পায়, তাই যে ওয়ার্কফ্লো sudo কল করে তা সফল হবে যদি রানার ইউজার sudo ব্যবহার করতে পারে। এমন একজন আনপ্রিভিলেজড ইউজার তৈরি করুন যার নিজের হোম ডিরেক্টরি ছাড়া আর কিছুর মালিকানা নেই। VPS-এ ন্যূনতম প্রিভিলেজড ইউজার অ্যাকাউন্ট সাধারণ নিয়মটি কভার করে। এখানে নির্দিষ্ট নিয়মটি দেওয়া হলো।
sudo useradd -m -s /bin/bash gharunner
sudo passwd -l gharunner
sudo chmod 750 /home/gharunner
sudo install -d -m 700 -o gharunner -g gharunner /home/gharunner/actions-runnerpasswd -l পাসওয়ার্ড লক করে দেয়, তাই কেউ পাসওয়ার্ড দিয়ে gharunner হিসেবে লগ ইন করতে পারবে না। রানার ডিরেক্টরিতে 700 মোড গুরুত্বপূর্ণ কারণ রানার সেখানে তার ক্রেডেনশিয়ালগুলো প্লেইনটেক্সটে সংরক্ষণ করে এবং চেকআউটে প্রাইভেট সোর্স থাকতে পারে।
সামনে এগিয়ে যাওয়ার আগে উভয় বৈশিষ্ট্য যাচাই করুন:
sudo passwd -S gharunner
sudo -l -U gharunnerpasswd -S একটি লাইন প্রিন্ট করে যা gharunner L দিয়ে শুরু হয়, যেখানে L মানে পাসওয়ার্ড লক করা আছে। sudo -l -U gharunner এর উত্তরে is not allowed to run sudo আসা উচিত। যদি এটি পরিবর্তে অনুমোদিত কমান্ডের একটি তালিকা প্রিন্ট করে, তবে অ্যাকাউন্টটি একটি sudo গ্রুপে আছে এবং আপনি যে আইসোলেশন তৈরি করেছেন তা নষ্ট হয়ে গেছে।
রানার ডাউনলোড করুন এবং টারবল (tarball) যাচাই করুন
এখান থেকে runner ব্যবহারকারী হিসেবে কাজ করুন।
sudo -iu gharunner
cd ~/actions-runner
RUNNER_VERSION=2.336.0
curl -fL -o actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
"https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz"আপনার আর্কিটেকচার সম্পর্কে নিশ্চিত না হলে প্রথমে uname -m চালান। x86_64 উপরের linux-x64 ফাইলটি গ্রহণ করে। aarch64 কমান্ডটি actions-runner-linux-arm64-${RUNNER_VERSION}.tar.gz গ্রহণ করে।
এখন আপনি যা ডাউনলোড করেছেন তা যাচাই করুন। নিচের SHA256 (সিকিউর হ্যাশ অ্যালগরিদম, 256 বিট) মানটি 2.336.0 x64 টারবলের জন্য। GitHub তাদের রিলিজ পেজে এবং New self-hosted runner স্ক্রিনে বর্তমান রিলিজের জন্য এই মানটি প্রদর্শন করে। প্রতিটি ভার্সনের সাথে এটি পরিবর্তিত হয়, তাই ভিন্ন কোনো ভার্সন ইনস্টল করার সময় সেখান থেকে এটি কপি করে নিন।
echo "04cf0be1aff4c3ec3554466c39124ca250e3effd8873bb7e8d68535aa9505d5d actions-runner-linux-x64-2.336.0.tar.gz" | sha256sum -cসঠিকভাবে ডাউনলোড হলে একটি লাইন দেখাবে:
actions-runner-linux-x64-2.336.0.tar.gz: OKফাইলটি অসম্পূর্ণ বা পরিবর্তিত হলে এটি ব্যর্থতা এবং একটি সতর্কবার্তা দেখাবে:
actions-runner-linux-x64-2.336.0.tar.gz: FAILED
sha256sum: WARNING: 1 computed checksum did NOT matchএই যাচাইকরণ প্রক্রিয়াটি এড়িয়ে যাবেন না এবং সমস্যাটি খুঁজে বের করার জন্য tar-এর ওপর নির্ভর করবেন না। একটি অসম্পূর্ণ আর্কাইভ gzip: stdin: unexpected end of file এবং tar: Unexpected EOF in archive ত্রুটি দেখাবে, যা আপনাকে জানাবে যে ফাইলটি ক্ষতিগ্রস্ত, কিন্তু এটি ফাইলটি কেটে ছোট করা হয়েছে নাকি প্রতিস্থাপন করা হয়েছে তা বলবে না।
tar xzf ./actions-runner-linux-x64-2.336.0.tar.gz
lsটারবলটিতে কী থাকে এবং কী থাকে না
এক্সট্রাকশনের পর ডিরেক্টরিটিতে config.sh, run.sh, env.sh, safe_sleep.sh, bin/ এবং externals/ থাকে। bin/-এ রানার বাইনারি এবং bin/installdependencies.sh থাকে। externals/-এ বান্ডেল করা Node রানটাইম থাকে, যার ওপর JavaScript অ্যাকশনগুলো কার্যকর হয়।
এখনও কোনো svc.sh নেই। GitHub-এর ডকুমেন্টেশনে এটিকে সেই স্ক্রিপ্ট হিসেবে বর্ণনা করা হয়েছে "যা রানার সফলভাবে যোগ করার পর তৈরি হয়", কারণ এটি একটি টেমপ্লেট থেকে লেখা হয় যেখানে আপনার রিপোজিটরি এবং রানারের নাম সার্ভিস নামের সাথে যুক্ত থাকে। তাই ./config.sh-এর আগে sudo ./svc.sh install চালালে তা sudo: ./svc.sh: command not found ত্রুটির কারণে ব্যর্থ হয়। প্রথমে রেজিস্টার করুন, তারপর সার্ভিসটি ইনস্টল করুন।
রানার ডিপেন্ডেন্সি ইনস্টল করা
রানার একটি .NET অ্যাপ্লিকেশন, তাই এর জন্য কিছু শেয়ার্ড লাইব্রেরির প্রয়োজন হয়। রানার ইউজারের শেল থেকে বেরিয়ে আসুন এবং sudo ব্যবহার করে এগুলো ইনস্টল করুন, কারণ স্ক্রিপ্টটি সিস্টেম প্যাকেজ ডেটাবেসে রাইট করে।
exit
cd /home/gharunner/actions-runner
sudo ./bin/installdependencies.shUbuntu 24.04-এ এটি libkrb5-3, zlib1g, liblttng-ust1t64, libssl3t64 এবং libicu74 ডাউনলোড করে। স্ক্রিপ্টটি প্রতিটি লাইব্রেরির জন্য বেশ কয়েকটি ভার্সন নেম যাচাই করে এবং আপনার রিলিজের সাথে সামঞ্জস্যপূর্ণ ভার্সনটি রাখে; এই কারণেই একই স্ক্রিপ্ট পুরনো Ubuntu এবং Debian-এ কাজ করে।
এই ধাপটি এড়িয়ে গেলে ./config.sh কোনো কাজ করার আগেই থেমে যাবে:
Dependencies is missing for Dotnet Core 6.0
Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies.libicu অনুপস্থিত থাকলে ভিন্ন একটি প্রথম লাইনের অধীনে একই পরামর্শ পাওয়া যায়, যা হলো Libicu's dependencies is missing for Dotnet Core 6.0। উভয়ই একই জায়গা থেকে আসে: config.sh শুরু হওয়ার আগে বান্ডেল করা লাইব্রেরিগুলোর বিপরীতে ldd রান করে, যাতে কোনো unresolved link থাকলে তা বিভ্রান্তিকর ক্র্যাশ তৈরি না করে স্ক্রিপ্টটিকে থামিয়ে দেয়।
আপনার রিপোজিটরির সাথে রানার রেজিস্টার করুন
রিপোজিটরি থেকে একটি টোকেন সংগ্রহ করুন। Settings খুলুন, তারপর Actions, তারপর Runners, এবং সবশেষে New self-hosted runner-এ যান। এই পৃষ্ঠায় একটি রেজিস্ট্রেশন টোকেন দেখানো হবে যা A দিয়ে শুরু হয়। এটি তৈরির এক ঘণ্টা পর মেয়াদোত্তীর্ণ হয়ে যায়, তাই যখন আপনি এটি পেস্ট করতে প্রস্তুত থাকবেন তখনই এটি তৈরি করুন।
রানার ইউজার হিসেবে রেজিস্টার করুন। config.sh, sudo-এর অধীনে চলতে অস্বীকার করে।
sudo -iu gharunner
cd ~/actions-runner
./config.sh --url https://github.com/YOUR-USER/YOUR-REPO \
--token PASTE_REGISTRATION_TOKEN_HERE \
--name vps-runner-1 \
--labels vps \
--work _work \
--unattended \
--replaceএই ফ্ল্যাগগুলো যা করে। --name হলো রিপোজিটরিতে রানারটি যেভাবে প্রদর্শিত হবে, তাই এমন কিছু বেছে নিন যা আপনি ছয় মাস পরেও চিনতে পারবেন। --labels আপনার নিজস্ব লেবেল যোগ করে; রানারটিতে আগে থেকেই কোনো অনুরোধ ছাড়াই self-hosted, Linux এবং X64 থাকে। --work রানার ডিরেক্টরির ভেতরে চেকআউটগুলো যেখানে জমা হবে সেই ডিরেক্টরির নাম নির্ধারণ করে। --unattended ইন্টারঅ্যাক্টিভ প্রম্পটগুলোর ডিফল্ট উত্তর প্রদান করে, যা আপনার প্রয়োজন যখন কমান্ডটি কোনো স্ক্রিপ্টের ভেতরে থাকে। --replace একই নামের বিদ্যমান রেজিস্ট্রেশনকে ব্যর্থ না করে সেটির জায়গা দখল করে নেয়, যা সার্ভার পুনরায় তৈরি করার সময় আপনার প্রয়োজন হয়।
একটি সফল রান এই লাইনগুলোর মাধ্যমে শেষ হয়:
√ Runner successfully added
√ Runner connection is good
√ Settings Saved.রেজিস্ট্রেশনটি এখন রানার ডিরেক্টরিতে .runner, .credentials এবং .credentials_rsaparams হিসেবে থাকে। শেষের দুটি ফাইল GitHub-এর কাছে এই রানারটিকে শনাক্ত করে, তাই যে কেউ এগুলো পড়তে পারলে রানারটির ছদ্মবেশ ধারণ করতে পারবে। এই কারণেই ডিরেক্টরিটির মোড 700 রাখা হয়েছে এবং ইউজারের কোনো sudo সুবিধা নেই।
systemd সার্ভিস হিসেবে রানার ইনস্টল করা
টার্মিনালে ./run.sh চালানো একটি পরীক্ষার জন্য ঠিক আছে, কিন্তু আপনার SSH সেশন বন্ধ হয়ে গেলে এটিও বন্ধ হয়ে যায়। সার্ভিসটি ইনস্টল করুন যাতে সিস্টেম বুট হওয়ার সময় রানার স্বয়ংক্রিয়ভাবে চালু হয়। VPS-এ systemd সার্ভিস এবং টাইমার অংশে ইউনিট ফাইলগুলো সম্পর্কে ব্যাখ্যা করা হয়েছে। এখানে svc.sh আপনার জন্য একটি ইউনিট ফাইল তৈরি করে দেবে।
exit
cd /home/gharunner/actions-runner
sudo ./svc.sh install gharunner
sudo ./svc.sh start
sudo ./svc.sh statussvc.sh চালানোর জন্য root অনুমতির প্রয়োজন হয়, কারণ এটি /etc/systemd/system ডিরেক্টরিতে একটি ইউনিট ফাইল লেখে এবং সেটি সক্রিয় করে। install-এর পরের আর্গুমেন্টটি হলো সেই ইউজার, যার অধীনে সার্ভিসটি চলবে। স্পষ্টভাবে gharunner পাস করুন। কোনো আর্গুমেন্ট না দিলে স্ক্রিপ্টটি ডিফল্টভাবে $SUDO_USER ব্যবহার করে, যা আপনার অ্যাডমিন অ্যাকাউন্ট। সেক্ষেত্রে প্রতিটি জব এমন একজন ইউজারের অধীনে চলবে যার sudo ব্যবহারের ক্ষমতা আছে।
ইউনিটটির নামকরণ করা হয় রিপোজিটরি এবং রানারের নামানুসারে, যা actions.runner.YOUR-USER-YOUR-REPO.vps-runner-1.service ফরম্যাটে থাকে। আপনাকে এটি টাইপ করার প্রয়োজন নেই:
systemctl list-units 'actions.runner.*'
sudo journalctl -u 'actions.runner.*' -n 20 --no-pagerএকটি সচল রানার √ Connected to GitHub লগ করে এবং এরপর একটি লাইন দেখায় যা Listening for Jobs দিয়ে শেষ হয়। রিপোজিটরির Runners পেজে এটিকে Idle হিসেবে দেখা যাবে। যদি রানার Offline দেখায়, তবে বুঝতে হবে এটি চলছে না অথবা 443 পোর্টে GitHub-এর সাথে সংযোগ স্থাপন করতে পারছে না।
রানারে একটি জব পাঠান
runs-on লেবেল ব্যবহার করে একটি রানার নির্বাচন করে। self-hosted এবং আপনার নিজস্ব লেবেল ব্যবহার করুন, যাতে জবটি আপনার উদ্দেশ্যহীন কোনো রানারে না যায়।
name: build
on:
push:
branches: [main]
jobs:
build:
runs-on: [self-hosted, linux, vps]
steps:
- uses: actions/checkout@v5
- run: uname -aযদি জবটি Waiting for a runner to pick up this job-এ অপেক্ষা করে, তবে বুঝতে হবে লেবেলগুলো মিলছে না। runs-on-এর প্রতিটি লেবেল অবশ্যই রানারে থাকতে হবে, তাই একটি অতিরিক্ত শব্দ থাকলে জবটি কোনো ত্রুটির বার্তা ছাড়াই কিউতে (queued) আটকে থাকবে। রিপোজিটরি সেটিংসে রানারের পাশে প্রদর্শিত লেবেলগুলোর সাথে আপনার তালিকার তুলনা করুন।
কেন সেলফ-হোস্টেড রানার এবং পাবলিক রিপোজিটরি একসাথে ব্যবহার করা উচিত নয়
এটি এমন একটি অংশ যা মানুষ এড়িয়ে যায়। GitHub-এর নির্দেশনা স্পষ্ট: সেলফ-হোস্টেড রানার "পাবলিক রিপোজিটরির জন্য প্রায় কখনোই ব্যবহার করা উচিত নয়" এবং এগুলোর "অস্থায়ী ক্লিন ভার্চুয়াল মেশিনে চলার কোনো নিশ্চয়তা নেই, এবং ওয়ার্কফ্লোতে থাকা অনির্ভরযোগ্য কোড দ্বারা এগুলো স্থায়ীভাবে ক্ষতিগ্রস্ত (compromised) হতে পারে"।
এর কার্যপদ্ধতি সহজ। একটি ফর্ক (fork) থেকে আসা পুল রিকোয়েস্ট তার নিজস্ব ওয়ার্কফ্লো ফাইলের কপি নিয়ে আসে। যদি আপনার পাবলিক রিপোজিটরি আপনার রানারে পুল রিকোয়েস্ট ওয়ার্কফ্লো চালায়, তবে যে কেউ রিপোজিটরি ফর্ক করে এমন একটি ওয়ার্কফ্লো প্রস্তাব করতে পারে যা আপনার VPS-এ তাদের কমান্ড চালাবে। তাদের কোনো রাইট অ্যাক্সেসের প্রয়োজন নেই, কারণ তারা যা প্রস্তাব করছে সেটিই রানারকে দিয়ে কাজ করায়।
অনুমোদনের সেটিংস এই ঝুঁকি কিছুটা কমায় কিন্তু পুরোপুরি সমাধান করে না। পাবলিক রিপোজিটরির ডিফল্ট পলিসি অনুযায়ী, একজন মেইনটেইনারকে প্রথমবার কন্ট্রিবিউট করা ব্যক্তির ফর্ক ওয়ার্কফ্লো অনুমোদন করতে হয়। একবার আপনি সেই ব্যক্তিকে অনুমোদন দিলে, তাদের পরবর্তী পুল রিকোয়েস্টগুলো নতুন কোনো প্রম্পট ছাড়াই চলে। তাই এই নিরাপত্তা ব্যবস্থাটি প্রতিবার একজন মানুষের ডিফের (diff) ওপর নির্ভরশীল, এবং বিল্ড স্ক্রিপ্টের তিন স্তর গভীরে লুকিয়ে রাখা কোনো পেলোড সহজে চোখ এড়িয়ে যেতে পারে।
একটি ফর্ক পুল রিকোয়েস্ট আপনার সিক্রেটগুলো পায় না এবং এর GITHUB_TOKEN রিড-অনলি থাকে। এটি GitHub-এর ভেতরে ক্ষতির পরিমাণ সীমিত করে। কিন্তু এটি আপনার সার্ভারের জন্য কোনো সুরক্ষা দেয় না। আক্রমণকারীর কাছে gharunner হিসেবে একটি শেল থাকে, তাই তারা সেই ব্যবহারকারীর পড়া সম্ভব এমন প্রতিটি ফাইল পড়তে পারে, প্রাইভেট নেটওয়ার্কে VPS-এর নাগাল পায় এমন যেকোনো কিছুতে পৌঁছাতে পারে এবং ~/.bashrc বা ব্যবহারকারীর systemd ইউনিটে এমন কিছু রেখে দিতে পারে যা পরবর্তী কাজের সময় চলবে।
--ephemeral দিয়ে রেজিস্টার করলে রানার একটি কাজ সম্পন্ন করে ডি-রেজিস্টার হয়ে যায়, তাই একটি কাজ অন্য কাজের ওয়ার্কস্পেস পড়তে পারে না। এটি কেবল তখনই সাহায্য করে যদি প্রতিটি কাজের জন্য মেশিন বা কন্টেইনার নতুন করে তৈরি করা হয়, কারণ রানার ব্যবহারকারীর হোম ডিরেক্টরিতে লেখা কোনো ব্যাকডোর নতুন রেজিস্ট্রেশনের পরেও থেকে যায়।
নিচের নিয়মগুলো সংক্ষিপ্ত। সেলফ-হোস্টেড রানার শুধুমাত্র প্রাইভেট রিপোজিটরির জন্য ব্যবহার করুন। যদি পাবলিক রিপোজিটরিতে এটি যুক্ত করতেই হয়, তবে সেখানে ফর্ক পুল রিকোয়েস্ট চালাবেন না, সেই সার্ভারে অন্য কিছু রাখবেন না এবং মেশিনটিকে ডিসপোজেবল (ব্যবহার শেষে ফেলে দেওয়ার যোগ্য) হিসেবে গণ্য করুন।
Docker জব এবং যে গ্রুপটি প্রকৃতপক্ষে root
কন্টেইনার জব, সার্ভিস কন্টেইনার এবং docker build কল করে এমন যেকোনো ওয়ার্কফ্লো স্টেপের জন্য রানার হোস্টে একটি Docker ডেমনের প্রয়োজন হয়। সাধারণ নিয়মে Docker ইনস্টল করুন, যা VPS-এ Docker এবং Docker Compose-এ আলোচনা করা হয়েছে, এরপর রানার ব্যবহারকারীকে docker গ্রুপে যুক্ত করুন।
এটি করার আগে এর ঝুঁকিগুলো বুঝে নিন। docker গ্রুপের সদস্যপদ থাকা মানেই root-এর সমান ক্ষমতা থাকা, কারণ একটি কন্টেইনার /-কে বাইন্ড মাউন্ট করতে পারে এবং এর ভেতরে root হিসেবে চলতে পারে। সুতরাং, যে ওয়ার্কফ্লো Docker সকেটের সাথে যোগাযোগ করতে পারে, সেটি /etc/shadow সহ VPS-এর প্রতিটি ফাইল পড়তে এবং লিখতে পারে। একটি প্রাইভেট রিপোজিটরি যেখানে বিশ্বস্ত কন্ট্রিবিউটর রয়েছে, সেখানে এটি হয়তো গ্রহণযোগ্য হতে পারে। অন্য যেকোনো ক্ষেত্রে এটি আনপ্রিভিলেজড ব্যবহারকারীর মূল উদ্দেশ্যকেই নষ্ট করে দেয়। Rootless Docker কন্টেইনার বিল্ডগুলোকে রানার ব্যবহারকারীর নিজস্ব অধিকারের ভেতরে সীমাবদ্ধ রাখে, তবে এর বিনিময়ে স্টোরেজ ড্রাইভার ধীরগতির হয় এবং প্রিভিলেজড কন্টেইনার ব্যবহার করা যায় না।
আপডেট এবং রানারকে সঠিকভাবে মুছে ফেলা
একটি সেলফ-হোস্টেড রানার ডিফল্টভাবে নিজেকে আপডেট করে নেয়। এটি নতুন কোনো রিলিজ শনাক্ত করলে নিজের ফাইলগুলো প্রতিস্থাপন করে এবং সার্ভিসটি রিস্টার্ট করে, তাই সাধারণত আপনাকে কিছুই করতে হয় না। যখন আপনার একটি নির্দিষ্ট ভার্সনের প্রয়োজন হয়, তখন ./config.sh --disableupdate সেলফ-আপডেট বন্ধ করে দেয়। এরপর, আপডেট করার দায়িত্ব আপনার: GitHub-এর ডকুমেন্টেশনে স্পষ্টভাবে বলা আছে যে --disableupdate দিয়ে কনফিগার করা রানারকে হাতে আপডেট করতে হবে।
ম্যানুয়াল আপডেটে রেজিস্ট্রেশন বজায় থাকে, কারণ .runner এবং .credentials টারবল (tarball)-এর মধ্যে থাকে না। সার্ভিসটি বন্ধ করুন, নতুন টারবল ডাউনলোড করুন এবং gharunner হিসেবে চেকসাম যাচাই করুন, tar xzf ব্যবহার করে একই ডিরেক্টরিতে এটি এক্সট্র্যাক্ট করুন, তারপর সার্ভিসটি পুনরায় চালু করুন:
cd /home/gharunner/actions-runner
sudo ./svc.sh stop
sudo ./svc.sh startরানারকে মুছে ফেলার জন্য, প্রথমে সার্ভিসটি আনইনস্টল করুন, তারপর ডি-রেজিস্টার করুন। রিমুভাল টোকেনটি একই Runners পেজ থেকে, রানারের নিজস্ব Remove বাটনের নিচে পাওয়া যাবে।
cd /home/gharunner/actions-runner
sudo ./svc.sh stop
sudo ./svc.sh uninstall
sudo -iu gharunner
cd ~/actions-runner
./config.sh remove --token PASTE_REMOVAL_TOKEN_HEREডি-রেজিস্টার না করে ডিরেক্টরি মুছে ফেললে রানারটি রিপোজিটরিতে Offline হিসেবে তালিকাভুক্ত থাকে, কারণ রানার নিজে থেকে না জানালে অথবা কোনো অ্যাডমিন হাতে এন্ট্রিটি মুছে না ফেললে GitHub এটি মুছে যাওয়ার বিষয়টি জানতে পারে না।
ব্যর্থতার ধরন এবং যে বার্তাগুলো আপনি দেখবেন
Must not run with sudo। config.sh যখন root হিসেবে চালানো হয়, তখন এটি এই বার্তাটি প্রদর্শন করে এবং বন্ধ হয়ে যায়। এই পরীক্ষাটি ইচ্ছাকৃতভাবে রাখা হয়েছে, কারণ _work-এ root-এর মালিকানাধীন ফাইল থাকলে পরবর্তীতে সার্ভিস ইউজার হিসেবে চালানো প্রতিটি কাজ ব্যর্থ হয়। ./config.sh-কে gharunner হিসেবে চালান। RUNNER_ALLOW_RUNASROOT ভেরিয়েবলটি এই পরীক্ষাকে এড়িয়ে যায়, তবে এটি ব্যবহার করলে সমস্যাটি কেবল পরবর্তী কোনো ধাপে গিয়ে দেখা দেয়।
sudo: ./svc.sh: command not found। আপনি সঠিক ডিরেক্টরিতে আছেন। svc.sh এখনো তৈরি হয়নি, কারণ config.sh এখনো রেজিস্ট্রেশন সম্পন্ন করেনি। রানারটিকে রেজিস্টার করুন, তারপর সার্ভিসটি ইনস্টল করুন।
Http response code: NotFound from 'POST https://api.github.com/actions/runner-registration'। টোকেনটি একটি বৈধ রেজিস্ট্রেশন টোকেন নয়। এটি হয়তো মেয়াদোত্তীর্ণ হয়েছে, কারণ এগুলোর মেয়াদ এক ঘণ্টা থাকে, অথবা Runners পেজ থেকে পাওয়া রেজিস্ট্রেশন টোকেনের পরিবর্তে একটি পার্সোনাল অ্যাক্সেস টোকেন পেস্ট করা হয়েছে। একটি নতুন টোকেন তৈরি করুন এবং পুনরায় পেস্ট করুন।
Dependencies is missing for Dotnet Core 6.0। রানার ডিরেক্টরি থেকে root হিসেবে sudo ./bin/installdependencies.sh চালান, তারপর পুনরায় রেজিস্টার করুন।
রিবুটের পর রানার অফলাইন। systemctl is-enabled 'actions.runner.*' চালান। যদি কোনো কিছু তালিকাভুক্ত না হয়, তবে ./svc.sh install কখনোই চালানো হয়নি, যার ফলে রানারটি কেবল আপনার টার্মিনাল সেশনের ভেতরেই বিদ্যমান ছিল। যদি ইউনিটটি এনাবল করা থাকে এবং রানারটি এখনো অফলাইন দেখায়, তবে journalctl -u 'actions.runner.*' পড়ুন এবং আউটবাউন্ড HTTPS সংযোগ পরীক্ষা করুন।
ডিস্ক পূর্ণ হয়ে যাওয়া। চেকআউট, বিল্ড ক্যাশ এবং Docker ইমেজগুলো _work-এর অধীনে এবং রানার ইউজারের হোম ডিরেক্টরিতে জমা হতে থাকে এবং এগুলো স্বয়ংক্রিয়ভাবে মুছে ফেলার কোনো ব্যবস্থা নেই। du -sh /home/gharunner/actions-runner/_work পর্যবেক্ষণ করুন এবং ডিস্ক পূর্ণ হওয়ার আগেই একটি নিয়মিত ক্লিন-আপের সময়সূচী নির্ধারণ করুন।
FAQ
কেন sudo ./svc.sh install কমান্ডটি খুঁজে পাওয়া যাচ্ছে না বলে জানায়?
কারণ svc.sh রানার টারবল (tarball)-এর মধ্যে থাকে না। ./config.sh রেজিস্ট্রেশন সম্পন্ন করার সময় আপনার রিপোজিটরি এবং রানারের নাম ব্যবহার করে সার্ভিস নেম তৈরি করার মাধ্যমে এটি রানার ডিরেক্টরিতে জেনারেট হয়। প্রথমে রানার ইউজার হিসেবে ./config.sh রান করুন। এরপর, sudo ./svc.sh install gharunner স্ক্রিপ্টটি খুঁজে পাবে এবং /etc/systemd/system-এ actions.runner.OWNER-REPO.RUNNER-NAME.service নামে একটি ইউনিট ফাইল লিখবে।
সেলফ-হোস্টেড রানারের জন্য কি ফায়ারওয়াল পোর্ট খোলার প্রয়োজন আছে?
না। রানার GitHub-এর সাথে একটি আউটবাউন্ড HTTPS কানেকশন তৈরি করে এবং জব পাওয়ার অপেক্ষায় সেটি খোলা রাখে, তাই GitHub কখনোই আপনার VPS-এ কানেকশন শুরু করে না। আউটবাউন্ড 443 পোর্টটি অনুমতি দিন এবং ইনবাউন্ড রুলগুলো বন্ধ রাখুন। সার্ভিস চলার সময় যদি রানার অফলাইন দেখায়, তবে ইনবাউন্ড রুলের পরিবর্তে আউটবাউন্ড ফিল্টারিং এবং DNS চেক করুন।
আমি কি পাবলিক রিপোজিটরিতে সেলফ-হোস্টেড রানার ব্যবহার করতে পারি?
আপনি পারেন, তবে GitHub এটি না করার পরামর্শ দেয়। একটি ফর্ক (fork) থেকে আসা পুল রিকোয়েস্টের নিজস্ব ওয়ার্কফ্লো ফাইল থাকে, তাই যে কেউ আপনার রিপোজিটরি ফর্ক করে আপনার মেশিনে কমান্ড চালানোর প্রস্তাব দিতে পারে। অনুমোদন প্রম্পটটি শুধুমাত্র একজন কন্ট্রিবিউটরের প্রথম রানের ক্ষেত্রে প্রযোজ্য। যদি আপনি একটি পাবলিক রিপোজিটরিতে রানার যুক্ত করেন, তবে সেটিতে ফর্ক পুল রিকোয়েস্ট ওয়ার্কফ্লো নিষ্ক্রিয় রাখুন, সেই সার্ভারে অন্য কিছু রাখবেন না এবং নিয়মিত বিরতিতে মেশিনটি রিবিল্ড করুন।
কেন Http response code: NotFound এর সাথে রেজিস্ট্রেশন ব্যর্থ হয়?
রেজিস্ট্রেশন কলটি শুধুমাত্র URL ভুল হলেই নয়, বরং ক্রেডেনশিয়াল ভুল হলেও NotFound উত্তর দেয়, যা মেসেজটিকে বিভ্রান্তিকর করে তোলে। রেজিস্ট্রেশন টোকেন দেখানোর এক ঘণ্টা পর মেয়াদোত্তীর্ণ হয়ে যায় এবং এই কলের জন্য পার্সোনাল অ্যাক্সেস টোকেন গ্রহণ করা হয় না। Settings, Actions, Runners, New self-hosted runner-এ পুনরায় যান, নতুন টোকেনটি কপি করুন এবং নিশ্চিত করুন যে --url ভ্যালুটি এমন একটি রিপোজিটরির দিকে নির্দেশ করছে যেখানে আপনার অ্যাডমিন অধিকার রয়েছে।