Cara Setup GitHub Actions Runner pada VPS Ubuntu 24.04
Panduan langkah demi langkah memasang GitHub Actions runner di VPS Ubuntu 24.04. Ketahui cara konfigurasi systemd, semakan checksum, dan risiko keselamatan pull request.
Apakah fungsi runner GitHub Actions yang dihoskan sendiri
Runner GitHub Actions yang dihoskan sendiri ialah program yang anda pasang pada VPS anda sendiri yang meminta tugasan daripada GitHub dan menjalankannya pada perkakasan anda. Anda mendaftarkannya pada satu repositori, memasangnya sebagai perkhidmatan systemd, dan ia akan aktif semula selepas setiap but semula. GitHub menjadualkan tugasan tersebut. Pelayan anda melakukan kerja itu.
CI (integrasi berterusan) pada mesin milik anda berbaloi atas dua sebab. Minit binaan tidak lagi dikira, dan sesuatu tugasan boleh mencapai perkara yang hanya ada pada mesin anda, seperti cache binaan yang sedia ada atau rangkaian peribadi. Harganya ialah keselamatan. Runner tersebut melaksanakan apa sahaja yang dinyatakan dalam fail aliran kerja, sebagai pengguna yang anda tetapkan, jadi fail aliran kerja sememangnya merupakan pelaksanaan kod jauh (remote code execution) mengikut reka bentuknya. Pada repositori peribadi, perkara ini tidak menjadi masalah kerana hanya orang yang anda percayai boleh menambah fail tersebut. Pada repositori awam, ia merupakan risiko sebenar, dan bahagian mengenai permintaan tarik (pull request) fork menjelaskan mekanismenya.
Segala yang dinyatakan di bawah adalah untuk Ubuntu 24.04 dengan runner versi 2.336.0, keluaran semasa setakat Julai 2026.
Keperluan sebelum bermula
Mulakan dengan VPS yang mempunyai akaun pentadbir biasa dan sudo, iaitu keadaan yang anda capai dalam sepuluh minit pertama pada VPS baharu. Anda tidak perlu membuka port masuk. Runner membuka sambungan HTTPS (hypertext transfer protocol secure) keluar ke GitHub dan membiarkannya terbuka sementara menunggu tugasan, jadi GitHub tidak pernah menyambung ke pelayan anda. Firewall anda boleh kekal tertutup kepada dunia luar dan tugasan masih akan sampai.
Anda juga memerlukan hak pentadbir pada repositori tersebut, kerana token pendaftaran dipaparkan dalam tetapan repositori.
Cipta pengguna khusus untuk runner
Jangan sekali-kali menjalankan runner sebagai root atau sebagai pengguna pentadbir anda sendiri. Setiap tugasan mewarisi hak pengguna runner, jadi aliran kerja yang memanggil sudo akan berjaya jika pengguna runner boleh menggunakan sudo. Cipta satu pengguna tanpa keistimewaan yang tidak memiliki apa-apa kecuali direktori rumahnya sendiri. Akaun pengguna dengan keistimewaan paling rendah pada VPS merangkumi corak umum ini. Berikut adalah corak khusus untuknya.
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 mengunci kata laluan, supaya tiada sesiapa boleh log masuk sebagai gharunner menggunakan kata laluan. Mod 700 pada direktori runner adalah penting kerana runner menyimpan kelayakannya di sana dalam bentuk teks jelas, dan daftar keluar (checkout) boleh mengandungi sumber peribadi.
Semak kedua-dua sifat ini sebelum anda meneruskan:
sudo passwd -S gharunner
sudo -l -U gharunnerpasswd -S mencetak baris yang bermula dengan gharunner L, di mana L bermaksud kata laluan dikunci. sudo -l -U gharunner sepatutnya menjawab dengan is not allowed to run sudo. Jika ia mencetak senarai arahan yang dibenarkan sebaliknya, akaun tersebut berada dalam kumpulan sudo dan pengasingan yang baru anda bina telah hilang.
Muat turun runner dan semak tarball
Bekerja sebagai pengguna runner mulai sekarang.
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"Jalankan uname -m terlebih dahulu jika anda tidak pasti tentang seni bina sistem. x86_64 mengambil fail linux-x64 di atas. aarch64 mengambil actions-runner-linux-arm64-${RUNNER_VERSION}.tar.gz.
Sekarang, sahkan apa yang telah anda muat turun. SHA256 (secure hash algorithm, 256 bit) di bawah adalah untuk tarball 2.336.0 x64. GitHub memaparkan nilai untuk keluaran semasa pada halaman keluaran dan pada skrin New self-hosted runner. Nilai ini berubah bagi setiap versi, jadi salin nilai tersebut dari sana apabila anda memasang versi yang berbeza.
echo "04cf0be1aff4c3ec3554466c39124ca250e3effd8873bb7e8d68535aa9505d5d actions-runner-linux-x64-2.336.0.tar.gz" | sha256sum -cMuat turun yang berjaya akan memaparkan satu baris:
actions-runner-linux-x64-2.336.0.tar.gz: OKFail yang terpotong atau diubah akan memaparkan kegagalan dan amaran:
actions-runner-linux-x64-2.336.0.tar.gz: FAILED
sha256sum: WARNING: 1 computed checksum did NOT matchJangan langkau pemeriksaan ini dan membiarkan tar mencari masalah tersebut kemudian. Arkib yang tidak lengkap akan gagal dengan gzip: stdin: unexpected end of file dan tar: Unexpected EOF in archive, yang memberitahu anda bahawa fail tersebut rosak tetapi tidak menyatakan sama ada ia terpotong atau telah diganti.
tar xzf ./actions-runner-linux-x64-2.336.0.tar.gz
lsKandungan tarball dan perkara yang tidak disertakan
Selepas pengekstrakan, direktori tersebut mengandungi config.sh, run.sh, env.sh, safe_sleep.sh, bin/ dan externals/. bin/ menyimpan binari pelari (runner) dan bin/installdependencies.sh. externals/ menyimpan masa jalan (runtime) Node yang dibundel untuk pelaksanaan tindakan JavaScript.
svc.sh masih belum wujud. Dokumentasi GitHub menggambarkannya sebagai skrip "yang dicipta selepas berjaya menambah pelari", kerana ia ditulis daripada templat dengan nama repositori dan nama pelari anda yang disematkan ke dalam nama perkhidmatan. Oleh itu, sudo ./svc.sh install sebelum ./config.sh akan gagal dengan sudo: ./svc.sh: command not found. Lakukan pendaftaran terlebih dahulu, kemudian pasang perkhidmatan tersebut.
Pasang dependensi runner
Runner ini merupakan aplikasi .NET, jadi ia memerlukan beberapa pustaka kongsi. Keluar daripada shell pengguna runner dan pasangkannya menggunakan sudo, kerana skrip tersebut menulis ke pangkalan data pakej sistem.
exit
cd /home/gharunner/actions-runner
sudo ./bin/installdependencies.shPada Ubuntu 24.04, tindakan ini menarik libkrb5-3, zlib1g, liblttng-ust1t64, libssl3t64 dan libicu74. Skrip tersebut mencuba beberapa nama versi untuk setiap pustaka dan mengekalkan versi yang disertakan dalam keluaran anda, itulah sebabnya skrip yang sama berfungsi pada Ubuntu versi lama dan Debian.
Langkau langkah ini dan ./config.sh akan berhenti sebelum ia melakukan sebarang tindakan:
Dependencies is missing for Dotnet Core 6.0
Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies.libicu yang hilang akan memberikan nasihat yang sama di bawah baris pertama yang berbeza, Libicu's dependencies is missing for Dotnet Core 6.0. Kedua-duanya datang daripada tempat yang sama: config.sh menjalankan ldd terhadap pustaka yang dibundel sebelum ia bermula, jadi pautan yang tidak diselesaikan akan menghentikan skrip tersebut daripada menghasilkan ralat yang mengelirukan kemudian.
Daftar runner dengan repositori anda
Dapatkan token daripada repositori. Buka Settings, kemudian Actions, kemudian Runners, dan seterusnya New self-hosted runner. Halaman tersebut memaparkan token pendaftaran yang bermula dengan A. Token ini tamat tempoh sejam selepas ia dicipta, jadi jana token tersebut apabila anda bersedia untuk menampalnya.
Daftar sebagai pengguna runner. config.sh tidak akan berjalan di bawah 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 \
--replaceFungsi bendera tersebut adalah seperti berikut. --name ialah cara runner dipaparkan dalam repositori, jadi pilih nama yang masih boleh anda kenali dalam tempoh enam bulan. --labels menambah label anda sendiri; runner tersebut sudah pun membawa self-hosted, Linux dan X64 tanpa perlu diminta. --work menamakan direktori tempat daftar keluar (checkout) diletakkan, di dalam direktori runner. --unattended menjawab gesaan interaktif dengan nilai lalai, iaitu perkara yang anda perlukan apabila arahan tersebut diletakkan di dalam skrip. --replace mengambil alih pendaftaran sedia ada yang mempunyai nama yang sama dan bukannya gagal, iaitu perkara yang anda perlukan apabila anda membina semula pelayan.
Jalankan yang berjaya akan berakhir dengan baris berikut:
√ Runner successfully added
√ Runner connection is good
√ Settings Saved.Pendaftaran tersebut kini berada dalam direktori runner sebagai .runner, .credentials dan .credentials_rsaparams. Dua fail terakhir mengenal pasti runner ini kepada GitHub, jadi sesiapa yang boleh membacanya boleh menyamar sebagai runner tersebut. Itulah sebabnya direktori tersebut ditetapkan kepada mod 700 dan pengguna tidak mempunyai akses sudo.
Memasang runner sebagai perkhidmatan systemd
./run.sh dalam terminal adalah memadai untuk satu ujian, tetapi ia akan mati apabila sesi SSH anda tamat. Pasang perkhidmatan tersebut supaya runner bermula semasa but. perkhidmatan dan pemasa systemd pada VPS menjelaskan fail unit itu sendiri. Di sini svc.sh menulis satu untuk anda.
exit
cd /home/gharunner/actions-runner
sudo ./svc.sh install gharunner
sudo ./svc.sh start
sudo ./svc.sh statussvc.sh memerlukan root kerana ia menulis unit ke dalam /etc/systemd/system dan mendayakannya. Argumen selepas install ialah pengguna yang menjalankan perkhidmatan tersebut. Berikan gharunner secara eksplisit. Tanpa argumen, skrip akan kembali kepada $SUDO_USER, iaitu akaun pentadbir anda, dan kemudian setiap tugasan akan dijalankan sebagai pengguna yang boleh menggunakan sudo.
Unit tersebut dinamakan mengikut repositori dan runner, dalam bentuk actions.runner.YOUR-USER-YOUR-REPO.vps-runner-1.service. Anda tidak perlu menaipnya secara manual:
systemctl list-units 'actions.runner.*'
sudo journalctl -u 'actions.runner.*' -n 20 --no-pagerRunner yang sihat akan mencatat √ Connected to GitHub dan kemudian satu baris yang berakhir dengan Listening for Jobs, dan halaman Runners pada repositori akan memaparkannya sebagai Idle. Runner yang dipaparkan sebagai Offline bermakna ia tidak berjalan atau tidak dapat mencapai GitHub pada port 443.
Menghantar tugasan kepada runner
runs-on memilih runner mengikut label. Minta self-hosted berserta label anda sendiri, supaya tugasan tidak dihantar kepada runner yang tidak anda inginkan.
name: build
on:
push:
branches: [main]
jobs:
build:
runs-on: [self-hosted, linux, vps]
steps:
- uses: actions/checkout@v5
- run: uname -aJika tugasan menunggu di Waiting for a runner to pick up this job, label tersebut tidak sepadan. Setiap label dalam runs-on mesti wujud pada runner tersebut, jadi satu perkataan tambahan akan menyebabkan tugasan kekal dalam baris gilir tanpa sebarang ralat. Bandingkan senarai tersebut dengan label yang dipaparkan bersebelahan runner dalam tetapan repositori.
Mengapa runner yang dihoskan sendiri dan repositori awam tidak boleh digabungkan
Ini adalah bahagian yang sering diabaikan oleh pengguna. Panduan GitHub menyatakan dengan jelas: runner yang dihoskan sendiri "hampir tidak boleh digunakan untuk repositori awam", dan ia "tidak mempunyai jaminan untuk berjalan dalam mesin maya bersih yang sementara, serta boleh dikompromi secara berterusan oleh kod yang tidak dipercayai dalam aliran kerja".
Mekanismenya mudah. Permintaan tarik (pull request) daripada fork membawa salinan fail aliran kerja miliknya sendiri. Jika repositori awam anda menjalankan aliran kerja permintaan tarik pada runner anda, sesiapa sahaja yang boleh melakukan fork pada repositori tersebut boleh mencadangkan aliran kerja yang menjalankan arahan mereka pada VPS anda. Mereka tidak memerlukan akses tulis, kerana perkara yang mereka cadangkan itulah yang akan dijalankan.
Tetapan kelulusan mengurangkan risiko ini tetapi tidak menyelesaikannya. Dasar lalai untuk repositori awam meminta penyelenggara meluluskan aliran kerja fork daripada penyumbang kali pertama. Selepas anda meluluskan individu tersebut sekali, permintaan tarik mereka yang seterusnya akan berjalan tanpa sebarang gesaan baharu. Jadi, kawalan ini bergantung kepada manusia yang membaca diff setiap kali, dan muatan yang disembunyikan tiga tahap di dalam skrip binaan adalah mudah untuk terlepas pandang.
Permintaan tarik fork tidak menerima rahsia anda, dan GITHUB_TOKEN miliknya adalah baca sahaja. Ini mengehadkan kerosakan di dalam GitHub. Ia tidak memberi kesan kepada pelayan anda. Penyerang mempunyai shell sebagai gharunner, jadi mereka boleh membaca setiap fail yang boleh dibaca oleh pengguna tersebut, mencapai apa sahaja yang boleh dicapai oleh VPS pada rangkaian peribadinya, dan meninggalkan sesuatu di dalam ~/.bashrc atau unit systemd pengguna yang berjalan semasa tugasan seterusnya.
Mendaftar dengan --ephemeral menyebabkan runner menerima satu tugasan dan kemudian menyahdaftar, jadi satu tugasan tidak boleh membaca ruang kerja tugasan yang seterusnya. Ia hanya membantu jika sesuatu membina semula mesin atau kontena untuk setiap tugasan, kerana pintu belakang yang ditulis ke dalam direktori rumah pengguna runner akan kekal walaupun selepas pendaftaran baharu.
Peraturan yang berikut adalah ringkas. Gunakan runner yang dihoskan sendiri untuk repositori peribadi. Jika anda mesti menyambungkannya kepada repositori awam, jangan jalankan permintaan tarik fork padanya, jangan simpan apa-apa lagi pada pelayan tersebut, dan anggap mesin itu sebagai sesuatu yang boleh dilupuskan.
Tugasan Docker, dan kumpulan yang sebenarnya root
Tugasan kontena, kontena perkhidmatan, dan mana-mana langkah aliran kerja yang memanggil docker build memerlukan daemon Docker pada hos pelari. Pasang Docker dengan cara biasa, yang diliputi dalam Docker dan Docker Compose pada VPS, kemudian tambahkan pengguna pelari ke dalam kumpulan docker.
Fahami pertukaran tersebut sebelum anda melakukannya. Keahlian dalam kumpulan docker adalah setara dengan root, kerana kontena boleh melakukan bind mount pada / dan berjalan sebagai root di dalamnya. Jadi, aliran kerja yang boleh berhubung dengan soket Docker boleh membaca dan menulis setiap fail pada VPS, termasuk /etc/shadow. Pada repositori peribadi dengan penyumbang yang dipercayai, ini mungkin harga yang boleh diterima. Di tempat lain, ia menghilangkan tujuan pengguna tanpa keistimewaan. Rootless Docker mengekalkan binaan kontena dalam hak milik pengguna pelari itu sendiri, dengan kos pemacu storan yang lebih perlahan dan tiada kontena berkeistimewaan.
Kemas kini, dan membuang runner dengan bersih
Runner yang dihoskan sendiri mengemas kini dirinya secara lalai. Ia mengesan keluaran baharu, menggantikan failnya sendiri dan memulakan semula perkhidmatan, jadi biasanya anda tidak perlu melakukan apa-apa. ./config.sh --disableupdate mematikan kemas kini automatik apabila anda memerlukan versi tetap. Selepas itu, mengemas kini adalah tugas anda: dokumentasi GitHub menyatakan dengan jelas bahawa runner yang dikonfigurasikan dengan --disableupdate perlu dikemas kini secara manual.
Kemas kini manual mengekalkan pendaftaran, kerana .runner dan .credentials tiada dalam tarball. Hentikan perkhidmatan, muat turun dan lakukan checksum pada tarball baharu sebagai gharunner, ekstrak ia ke direktori yang sama dengan tar xzf, kemudian mulakan semula perkhidmatan:
cd /home/gharunner/actions-runner
sudo ./svc.sh stop
sudo ./svc.sh startUntuk membuang runner, nyahpasang perkhidmatan terlebih dahulu, kemudian nyahdaftar. Token pembuangan diperoleh daripada halaman Runners yang sama, di bawah butang Remove milik runner tersebut.
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_HEREMemadam direktori tanpa menyahdaftar akan menyebabkan runner disenaraikan sebagai Offline dalam repositori, kerana GitHub hanya mengetahui ia telah tiada apabila runner itu sendiri memaklumkannya atau pentadbir memadam entri tersebut secara manual.
Mod kegagalan, berserta rentetan yang akan anda lihat
Must not run with sudo. config.sh mencetak ini dan keluar apabila ia dijalankan sebagai root. Semakan ini adalah sengaja, kerana fail milik root dalam _work akan merosakkan setiap kerja seterusnya yang dijalankan sebagai pengguna perkhidmatan. Jalankan ./config.sh sebagai gharunner. Pemboleh ubah RUNNER_ALLOW_RUNASROOT mengatasi semakan ini, dan menggunakannya hanya akan menangguhkan kerosakan tersebut ke peringkat kemudian.
sudo: ./svc.sh: command not found. Anda berada dalam direktori yang betul. svc.sh belum wujud lagi, kerana config.sh belum melengkapkan pendaftaran. Daftarkan runner, kemudian pasang perkhidmatan tersebut.
Http response code: NotFound from 'POST https://api.github.com/actions/runner-registration'. Token tersebut bukan token pendaftaran yang sah. Sama ada ia telah tamat tempoh, memandangkan ia hanya bertahan selama satu jam, atau token akses peribadi telah ditampal menggantikan token pendaftaran daripada halaman Runners. Jana token baharu dan tampal sekali lagi.
Dependencies is missing for Dotnet Core 6.0. Jalankan sudo ./bin/installdependencies.sh daripada direktori runner sebagai root, kemudian daftar semula.
Runner Luar Talian selepas but semula. Jalankan systemctl is-enabled 'actions.runner.*'. Jika tiada apa-apa yang disenaraikan, ./svc.sh install tidak pernah dijalankan, jadi runner tersebut hanya wujud di dalam sesi terminal anda. Jika unit didayakan dan runner masih Luar Talian, baca journalctl -u 'actions.runner.*' dan periksa HTTPS keluar.
Cakera penuh. Daftar keluar, cache binaan dan imej Docker terkumpul di bawah _work dan dalam direktori utama pengguna runner, dan tiada apa-apa yang membersihkannya untuk anda. Pantau du -sh /home/gharunner/actions-runner/_work dan tambah pembersihan berjadual sebelum cakera membuat keputusan untuk anda.
FAQ
Mengapakah sudo ./svc.sh install menyatakan command not found?
Ini kerana svc.sh tiada dalam tarball runner. Ia dijana dalam direktori runner apabila ./config.sh selesai mendaftar, menggunakan nama repositori dan nama runner anda untuk membina nama perkhidmatan. Jalankan ./config.sh sebagai pengguna runner terlebih dahulu. Selepas itu, sudo ./svc.sh install gharunner akan menemui skrip tersebut dan menulis unit bernama actions.runner.OWNER-REPO.RUNNER-NAME.service ke dalam /etc/systemd/system.
Adakah saya perlu membuka port tembok api untuk runner yang dihoskan sendiri?
Tidak. Runner membuka sambungan HTTPS keluar ke GitHub dan mengekalkannya sementara menunggu tugasan, jadi GitHub tidak akan memulakan sambungan ke VPS anda. Benarkan trafik keluar 443 dan biarkan peraturan trafik masuk anda tertutup. Jika runner menunjukkan status Offline semasa perkhidmatannya berjalan, periksa penapisan trafik keluar dan DNS dan bukannya peraturan trafik masuk.
Bolehkah saya menggunakan runner yang dihoskan sendiri pada repositori awam?
Anda boleh, namun GitHub tidak mengesyorkannya. Permintaan tarik (pull request) daripada fork membawa fail aliran kerjanya sendiri, jadi sesiapa sahaja yang boleh melakukan fork pada repositori anda boleh mencadangkan arahan yang berjalan pada mesin anda. Gesaan kelulusan hanya meliputi percubaan pertama penyumbang. Jika anda melampirkan runner pada repositori awam, lumpuhkan aliran kerja permintaan tarik fork padanya, jangan simpan apa-apa lagi pada pelayan tersebut, dan bina semula mesin itu mengikut jadual.
Mengapakah pendaftaran gagal dengan Http response code: NotFound?
Panggilan pendaftaran menjawab NotFound apabila kelayakan salah, bukan hanya apabila URL salah, yang menjadikan mesej tersebut mengelirukan. Token pendaftaran tamat tempoh satu jam selepas ia dipaparkan, dan token akses peribadi tidak diterima untuk panggilan ini. Buka Settings, Actions, Runners, New self-hosted runner sekali lagi, salin token baharu, dan pastikan nilai --url menghala ke repositori di mana anda mempunyai hak pentadbir.