-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmanage_linux.sh
197 lines (190 loc) · 9.1 KB
/
manage_linux.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/bin/env bash
##Helper Script to Manage Self Hosted Linux Runners
#SELF: bash <(curl -qfsSL "https://raw.githubusercontent.com/pkgforge/devscripts/refs/heads/main/Github/Runners/manage_linux.sh")
#------------------------------------------------------------------------------------#
#Sanity Checks
if [ -z "${GITHUB_PERSONAL_TOKEN}" ] || \
[ -z "${GITHUB_OWNER}" ] || \
[ -z "${RUNNER_NAME}" ] || \
[ -z "${RUNNER_LABELS}" ]; then
#exit
echo -e "\n[-] FATAL: Required ENV VARS NOT SET\n"
echo -e "GITHUB_PERSONAL_TOKEN=${GITHUB_PERSONAL_TOKEN}"
echo -e "GITHUB_OWNER=${GITHUB_OWNER}"
echo -e "RUNNER_NAME=${RUNNER_NAME}"
echo -e "RUNNER_LABELS=${RUNNER_LABELS}"
exit 1
elif [ -z "${GITHUB_REPOSITORY}" ] && [ -z "${GITHUB_ORG}" ]; then
#exit
echo -e "\n[-] FATAL: At least GITHUB_ORG or GITHUB_REPOSITORY must be specified\n"
echo -e "GITHUB_ORG=${GITHUB_ORG}"
echo -e "GITHUB_REPOSITORY=${GITHUB_REPOSITORY}"
exit 1
fi
#------------------------------------------------------------------------------------#
#------------------------------------------------------------------------------------#
##Start Docker
#Check for kernel modules
sudo systemctl stop docker 2>/dev/null
sudo cp -au "/var/lib/docker" "/var/lib/docker.bk"
sudo modprobe -n -q "fuse"
fuse_overlayfs_status=$?
sudo modprobe -n -q "btrfs"
btrfs_status=$?
if [[ $fuse_overlayfs_status -ne 0 && $btrfs_status -ne 0 ]]; then
sudo modprobe "fuse" ; sudo modprobe "btrfs"
echo -e "\n[+] Configuring Docker to use vfs\n"
sudo rm -rf "/var/lib/docker/"
if [[ ! -f "/etc/docker/daemon.json" ]]; then
sudo mkdir -p "/etc/docker"
echo '{"storage-driver": "vfs"}' | jq . | sudo tee -a "/etc/docker/daemon.json"
else
sudo sed 's/"storage-driver": "fuse-overlayfs"/"storage-driver": "vfs"/' -i "/etc/docker/daemon.json"
sudo sed 's/"storage-driver": "btrfs"/"storage-driver": "vfs"/' -i "/etc/docker/daemon.json"
jq . "/etc/docker/daemon.json"
fi
sudo cp -au "/var/lib/docker.bk/." "/var/lib/docker/" && sudo rm -rf "/var/lib/docker.bk"
elif sudo grep -q 'btrfs' "/proc/filesystems" && sudo modprobe -n -q "btrfs"; then
echo -e "\n[+] Configuring Docker to use btrfs\n"
sudo rm -rf "/var/lib/docker/"
sudo mkfs.btrfs -f "/dev/xvdf" "/dev/xvdg"
sudo mount -t btrfs "/dev/xvdf" "/var/lib/docker"
if [[ ! -f "/etc/docker/daemon.json" ]]; then
echo '{"storage-driver": "btrfs"}' | jq . | sudo tee -a "/etc/docker/daemon.json"
else
sed 's/"storage-driver": "fuse-overlayfs"/"storage-driver": "btrfs"/' -i "/etc/docker/daemon.json"
sed 's/"storage-driver": "vfs"/"storage-driver": "btrfs"/' -i "/etc/docker/daemon.json"
jq . "/etc/docker/daemon.json"
fi
sudo cp -au "/var/lib/docker.bk/." "/var/lib/docker/" && sudo rm -rf "/var/lib/docker.bk"
fi
##Restart Services
if command -v systemctl &>/dev/null && [ -s "/lib/systemd/system/docker.service" ]; then
echo -e "\n[+] Starting supervisor (Docker)\n"
sudo systemctl daemon-reload 2>/dev/null
sudo systemctl enable docker --now 2>/dev/null
sudo systemctl list-unit-files --type=service | grep -i "docker"
if sudo systemctl is-active --quiet docker; then
echo -e "\n[+] Docker is Active\n"
sudo systemctl status "docker.service" --no-pager
else
echo -e "\n[+] Restarting Docker (1/2) ...\n"
sudo service docker restart >/dev/null 2>&1 ; sleep 20
if sudo systemctl is-active --quiet docker; then
echo -e "\n[+] Docker is Active\n"
sudo systemctl status "docker.service" --no-pager
else
echo -e "\n[+] Restarting Docker (2/2) ...\n"
sudo service docker restart >/dev/null 2>&1 ; sleep 20
sudo systemctl status "docker.service" --no-pager
fi
fi
#if ! sudo systemctl is-active --quiet docker; then
if sudo systemctl is-active --quiet docker; then
sudo docker info
else
echo "[-] FATAL: Multiple Attempts to restart Docker Failed\nQuitting..."
sudo systemctl status "docker.service" --no-pager
exit 1
fi
fi
#------------------------------------------------------------------------------------#
#------------------------------------------------------------------------------------#
##Read from --env-file=runner.env & Authenticate
if [ -n "${GITHUB_REPOSITORY}" ]; then
echo -e "[+] Registering Runner For ${GITHUB_OWNER}/${GITHUB_REPOSITORY} [REPO]"
export AUTH_URL="https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners/registration-token"
export REG_URL="https://github.com/${GITHUB_OWNER}/${GITHUB_REPOSITORY}"
elif [ -n "${GITHUB_ORG}" ]; then
echo -e "[+] Registering Runner For ${GITHUB_ORG} [ORG]"
export AUTH_URL="https://api.github.com/orgs/${GITHUB_OWNER}/actions/runners/registration-token"
export REG_URL="https://github.com/${GITHUB_OWNER}"
fi
#------------------------------------------------------------------------------------#
#------------------------------------------------------------------------------------#
##Func to Generate API Tokens
generate_token() {
echo -e "[+] Generating Token..."
API_RESPONSE="$(curl -qfsSL -X 'POST' "${AUTH_URL}" -H "Authorization: Bearer ${GITHUB_PERSONAL_TOKEN}" -H 'Accept: application/vnd.github+json')" && export API_RESPONSE="${API_RESPONSE}"
#Validate Response
if ! echo "${API_RESPONSE}" | jq -e . >/dev/null 2>&1; then
echo "[-] Error: API response is not a valid JSON."
echo "${API_RESPONSE}"
unset RUNNER_TOKEN
exit 1
else
#Fetch Token
RUNNER_TOKEN="$(echo "${API_RESPONSE}" | jq -r '.token' | tr -d '[:space:]')" && export RUNNER_TOKEN="${RUNNER_TOKEN}"
if [ "${RUNNER_TOKEN}" == "null" ]; then
echo "[-] Error: Couldn't fetch Ephemeral AUTH Token."
echo "${API_RESPONSE}" | jq .
unset RUNNER_TOKEN
exit 1
else
echo -e "[+] Ephemeral AUTH Token :: ${RUNNER_TOKEN}"
fi
fi
}
export -f generate_token
#------------------------------------------------------------------------------------#
#------------------------------------------------------------------------------------#
##Register Runner
cd "/runner-init"
RUNNER_ID="${RUNNER_NAME}_$(openssl rand -hex 6 | tr -d '[:space:]')" && export RUNNER_ID="${RUNNER_ID}"
echo "[+] Registering Runner --> ${RUNNER_ID}" && generate_token
if [ -n "${RUNNER_TOKEN}" ]; then
##Configure
echo "[+] Configuring Runner..."
echo "[+] (ID: ${RUNNER_ID})"
echo "[+] (LABELS: ${RUNNER_LABELS})"
echo "[+] (TOKEN: ${RUNNER_TOKEN})"
echo "[+] (URL: ${REG_URL})"
"/runner-init/config.sh" \
--name "${RUNNER_ID}" \
--labels "${RUNNER_LABELS}" \
--token "${RUNNER_TOKEN}" \
--url "${REG_URL}" \
--unattended \
--replace \
--ephemeral
else
echo "[-] Failed to Generate Token..."
echo -e "\n[+] GITHUB_PERSONAL_TOKEN: ${GITHUB_PERSONAL_TOKEN}\n"
curl -fsSL "https://api.github.com/user" -H "Authorization: Bearer ${GITHUB_PERSONAL_TOKEN}" -H 'Accept: application/vnd.github+json'
exit 1
fi
#------------------------------------------------------------------------------------#
#------------------------------------------------------------------------------------#
##Remove Runner Upon Completion
remove_runner() {
generate_token
echo -e "\n[+] Removing Runners ...\n"
#Remove Offline Runners
if [ -n "${GITHUB_REPOSITORY}" ]; then
OFFLINE_RUNNERS="$(curl -qfsSL "https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners?per_page=100" -H "Authorization: Bearer ${GITHUB_PERSONAL_TOKEN}" -H 'Accept: application/vnd.github+json' | jq -r '.runners[] | select(.status == "offline") | .id')" && export OFFLINE_RUNNERS="${OFFLINE_RUNNERS}"
readarray -t OFFLINE_RUNNERS_ID <<< "${OFFLINE_RUNNERS}"
for R_ID in "${OFFLINE_RUNNERS_ID[@]}"; do
curl -qfsSL -X 'DELETE' "https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners/${R_ID}" -H "Authorization: Bearer ${GITHUB_PERSONAL_TOKEN}" -H 'Accept: application/vnd.github+json'
done
elif [ -n "${GITHUB_ORG}" ]; then
OFFLINE_RUNNERS="$(curl -qfsSL "https://api.github.com/orgs/${GITHUB_OWNER}/actions/runners?per_page=100" -H "Authorization: Bearer ${GITHUB_PERSONAL_TOKEN}" -H 'Accept: application/vnd.github+json' | jq -r '.runners[] | select(.status == "offline") | .id')" && export OFFLINE_RUNNERS="${OFFLINE_RUNNERS}"
readarray -t OFFLINE_RUNNERS_ID <<< "${OFFLINE_RUNNERS}"
for R_ID in "${OFFLINE_RUNNERS_ID[@]}"; do
curl -qfsSL -X 'DELETE' "https://api.github.com/orgs/${GITHUB_OWNER}/actions/runners/${R_ID}" -H "Authorization: Bearer ${GITHUB_PERSONAL_TOKEN}" -H 'Accept: application/vnd.github+json'
done
fi
#Remove Self
"/runner-init/config.sh" remove --unattended --token "${RUNNER_TOKEN}"
#Cleanup
unset API_RESPONSE AUTH_URL OFFLINE_RUNNERS_ID REG_URL RUNNERS_ID R_ID RUNNER_ID RUNNER_LABELS RUNNER_TOKEN
kill -9 $$
}
export -f remove_runner
#exit if ctrl + c
trap 'remove_runner; exit 130' SIGINT
#exit if kill|pkill -9
trap 'remove_runner; exit 143' SIGTERM
#------------------------------------------------------------------------------------#
#Run with Initial ARGs
"/runner-init/run.sh" "$*"
#------------------------------------------------------------------------------------#