https://dev.kronoz.win/r/marzneshin.git
1#!/usr/bin/env bash
2set -e
3
4APP_NAME="marzneshin"
5CONFIG_DIR="/etc/opt/$APP_NAME"
6DATA_DIR="/var/lib/$APP_NAME"
7COMPOSE_FILE="$CONFIG_DIR/docker-compose.yml"
8
9
10colorized_echo() {
11 local color=$1
12 local text=$2
13
14 case $color in
15 "red")
16 printf "\e[91m${text}\e[0m\n";;
17 "green")
18 printf "\e[92m${text}\e[0m\n";;
19 "yellow")
20 printf "\e[93m${text}\e[0m\n";;
21 "blue")
22 printf "\e[94m${text}\e[0m\n";;
23 "magenta")
24 printf "\e[95m${text}\e[0m\n";;
25 "cyan")
26 printf "\e[96m${text}\e[0m\n";;
27 *)
28 echo "${text}"
29 ;;
30 esac
31}
32
33check_running_as_root() {
34 if [ "$(id -u)" != "0" ]; then
35 colorized_echo red "This command must be run as root."
36 exit 1
37 fi
38}
39
40detect_os() {
41 # Detect the operating system
42 if [ -f /etc/lsb-release ]; then
43 OS=$(lsb_release -si)
44 elif [ -f /etc/os-release ]; then
45 OS=$(awk -F= '/^NAME/{print $2}' /etc/os-release | tr -d '"')
46 elif [ -f /etc/redhat-release ]; then
47 OS=$(cat /etc/redhat-release | awk '{print $1}')
48 elif [ -f /etc/arch-release ]; then
49 OS="Arch"
50 else
51 colorized_echo red "Unsupported operating system"
52 exit 1
53 fi
54}
55
56detect_and_update_package_manager() {
57 colorized_echo blue "Updating package manager"
58 if [[ "$OS" == "Ubuntu"* ]] || [[ "$OS" == "Debian"* ]]; then
59 PKG_MANAGER="apt-get"
60 $PKG_MANAGER update
61 elif [[ "$OS" == "CentOS"* ]] || [[ "$OS" == "AlmaLinux"* ]]; then
62 PKG_MANAGER="yum"
63 $PKG_MANAGER update -y
64 $PKG_MANAGER install -y epel-release
65 elif [ "$OS" == "Fedora"* ]; then
66 PKG_MANAGER="dnf"
67 $PKG_MANAGER update
68 elif [ "$OS" == "Arch" ]; then
69 PKG_MANAGER="pacman"
70 $PKG_MANAGER -Sy
71 else
72 colorized_echo red "Unsupported operating system"
73 exit 1
74 fi
75}
76
77detect_compose() {
78 # Check if docker compose command exists
79 if docker compose >/dev/null 2>&1; then
80 COMPOSE='docker compose'
81 elif docker-compose >/dev/null 2>&1; then
82 COMPOSE='docker-compose'
83 else
84 colorized_echo red "docker compose not found"
85 exit 1
86 fi
87}
88
89install_package () {
90 if [ -z $PKG_MANAGER ]; then
91 detect_and_update_package_manager
92 fi
93
94 PACKAGE=$1
95 colorized_echo blue "Installing $PACKAGE"
96 if [[ "$OS" == "Ubuntu"* ]] || [[ "$OS" == "Debian"* ]]; then
97 $PKG_MANAGER -y install "$PACKAGE"
98 elif [[ "$OS" == "CentOS"* ]] || [[ "$OS" == "AlmaLinux"* ]]; then
99 $PKG_MANAGER install -y "$PACKAGE"
100 elif [ "$OS" == "Fedora"* ]; then
101 $PKG_MANAGER install -y "$PACKAGE"
102 elif [ "$OS" == "Arch" ]; then
103 $PKG_MANAGER -S --noconfirm "$PACKAGE"
104 else
105 colorized_echo red "Unsupported operating system"
106 exit 1
107 fi
108}
109
110install_docker() {
111 # Install Docker and Docker Compose using the official installation script
112 colorized_echo blue "Installing Docker"
113 curl -fsSL https://get.docker.com | sh
114 colorized_echo green "Docker installed successfully"
115}
116
117install_marzneshin_script() {
118 FETCH_REPO="khodedawsh/marzneshin"
119 SCRIPT_URL="https://github.com/$FETCH_REPO/raw/master/script.sh"
120 colorized_echo blue "Installing marzneshin script"
121 curl -sSL $SCRIPT_URL | install -m 755 /dev/stdin /usr/local/bin/marzneshin
122 colorized_echo green "marzneshin script installed successfully"
123}
124
125install_marzneshin() {
126 # Fetch releases
127 FILES_URL_PREFIX="https://raw.githubusercontent.com/khodedawsh/marzneshin/master"
128
129 mkdir -p "$DATA_DIR"
130 mkdir -p "$CONFIG_DIR"
131
132 colorized_echo blue "Fetching compose file"
133 curl -sL "$FILES_URL_PREFIX/docker-compose.yml" -o "$CONFIG_DIR/docker-compose.yml"
134 colorized_echo green "File saved in $CONFIG_DIR/docker-compose.yml"
135
136 colorized_echo blue "Fetching .env file"
137 curl -sL "$FILES_URL_PREFIX/.env.example" -o "$CONFIG_DIR/.env"
138 sed -i 's/^# \(SQLALCHEMY_DATABASE_URL = .*\)$/\1/' "$CONFIG_DIR/.env"
139 sed -i 's~\(SQLALCHEMY_DATABASE_URL = \).*~\1"sqlite:///'$DATA_DIR'/db.sqlite3"~' "$CONFIG_DIR/.env"
140 colorized_echo green "File saved in $CONFIG_DIR/.env"
141
142 colorized_echo green "Marzneshin files downloaded successfully"
143}
144
145
146uninstall_marzneshin_script() {
147 if [ -f "/usr/local/bin/marzneshin" ]; then
148 colorized_echo yellow "Removing marzneshin script"
149 rm "/usr/local/bin/marzneshin"
150 fi
151}
152
153uninstall_marzneshin() {
154 if [ -d "$CONFIG_DIR" ]; then
155 colorized_echo yellow "Removing directory: $CONFIG_DIR"
156 rm -r "$CONFIG_DIR"
157 fi
158}
159
160uninstall_marzneshin_docker_images() {
161 images=$(docker images | grep marzneshin | awk '{print $3}')
162
163 if [ -n "$images" ]; then
164 colorized_echo yellow "Removing Docker images of Marzneshin"
165 for image in $images; do
166 if docker rmi "$image" >/dev/null 2>&1; then
167 colorized_echo yellow "Image $image removed"
168 fi
169 done
170 fi
171}
172
173uninstall_marzneshin_data_files() {
174 if [ -d "$DATA_DIR" ]; then
175 colorized_echo yellow "Removing directory: $DATA_DIR"
176 rm -r "$DATA_DIR"
177 fi
178}
179
180up_marzneshin() {
181 $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" up -d --remove-orphans
182}
183
184down_marzneshin() {
185 $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" down
186}
187
188show_marzneshin_logs() {
189 $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" logs
190}
191
192follow_marzneshin_logs() {
193 $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" logs -f
194}
195
196marzneshin_cli() {
197 $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" exec -e CLI_PROG_NAME="marzneshin cli" marzneshin /app/marzneshin-cli.py "$@"
198}
199
200
201update_marzneshin_script() {
202 FETCH_REPO="khodedawsh/marzneshin"
203 SCRIPT_URL="https://github.com/$FETCH_REPO/raw/master/script.sh"
204 colorized_echo blue "Updating marzneshin script"
205 curl -sSL $SCRIPT_URL | install -m 755 /dev/stdin /usr/local/bin/marzneshin
206 colorized_echo green "marzneshin script updated successfully"
207}
208
209update_marzneshin() {
210 $COMPOSE -f $COMPOSE_FILE -p "$APP_NAME" pull
211}
212
213is_marzneshin_installed() {
214 if [ -d $CONFIG_DIR ]; then
215 return 0
216 else
217 return 1
218 fi
219}
220
221is_marzneshin_up() {
222 if [ -z "$($COMPOSE -f $COMPOSE_FILE ps -q -a)" ]; then
223 return 1
224 else
225 return 0
226 fi
227}
228
229install_command() {
230 check_running_as_root
231 # Check if marzneshin is already installed
232 if is_marzneshin_installed; then
233 colorized_echo red "Marzneshin is already installed at $CONFIG_DIR"
234 read -p "Do you want to override the previous installation? (y/n) "
235 if [[ ! $REPLY =~ ^[Yy]$ ]]; then
236 colorized_echo red "Aborted installation"
237 exit 1
238 fi
239 fi
240 detect_os
241 if ! command -v jq >/dev/null 2>&1; then
242 install_package jq
243 fi
244 if ! command -v curl >/dev/null 2>&1; then
245 install_package curl
246 fi
247 if ! command -v docker >/dev/null 2>&1; then
248 install_docker
249 fi
250 detect_compose
251 install_marzneshin_script
252 install_marzneshin
253 up_marzneshin
254 follow_marzneshin_logs
255}
256
257uninstall_command() {
258 check_running_as_root
259 # Check if marzneshin is installed
260 if ! is_marzneshin_installed; then
261 colorized_echo red "Marzneshin's not installed!"
262 exit 1
263 fi
264
265 read -p "Do you really want to uninstall Marzneshin? (y/n) "
266 if [[ ! $REPLY =~ ^[Yy]$ ]]; then
267 colorized_echo red "Aborted"
268 exit 1
269 fi
270
271 detect_compose
272 if is_marzneshin_up; then
273 down_marzneshin
274 fi
275 uninstall_marzneshin_script
276 uninstall_marzneshin
277 uninstall_marzneshin_docker_images
278
279 read -p "Do you want to remove Marzneshin's data files too ($DATA_DIR)? (y/n) "
280 if [[ ! $REPLY =~ ^[Yy]$ ]]; then
281 colorized_echo green "Marzneshin uninstalled successfully"
282 else
283 uninstall_marzneshin_data_files
284 colorized_echo green "Marzneshin uninstalled successfully"
285 fi
286}
287
288up_command() {
289 help() {
290 colorized_echo red "Usage: $0 up [options]"
291 echo ""
292 echo "OPTIONS:"
293 echo " -h, --help display this help message"
294 echo " -n, --no-logs do not follow logs after starting"
295 }
296
297 local no_logs=false
298 while [[ "$#" -gt 0 ]]; do
299 case "$1" in
300 -n|--no-logs)
301 no_logs=true
302 ;;
303 -h|--help)
304 help
305 exit 0
306 ;;
307 *)
308 echo "Error: Invalid option: $1" >&2
309 help
310 exit 0
311 ;;
312 esac
313 shift
314 done
315
316 # Check if marzneshin is installed
317 if ! is_marzneshin_installed; then
318 colorized_echo red "Marzneshin is not installed!"
319 exit 1
320 fi
321
322 detect_compose
323
324 if is_marzneshin_up; then
325 colorized_echo red "Marzneshin is already up"
326 exit 1
327 fi
328
329 up_marzneshin
330 if [ "$no_logs" = false ]; then
331 follow_marzneshin_logs
332 fi
333}
334
335down_command() {
336
337 # Check if marzneshin is installed
338 if ! is_marzneshin_installed; then
339 colorized_echo red "Marzneshin's not installed!"
340 exit 1
341 fi
342
343 detect_compose
344
345 if ! is_marzneshin_up; then
346 colorized_echo red "Marzneshin's already down"
347 exit 1
348 fi
349
350 down_marzneshin
351}
352
353restart_command() {
354 help() {
355 colorized_echo red "Usage: $0 restart [options]"
356 echo
357 echo "OPTIONS:"
358 echo " -h, --help display this help message"
359 echo " -n, --no-logs do not follow logs after starting"
360 }
361
362 local no_logs=false
363 while [[ "$#" -gt 0 ]]; do
364 case "$1" in
365 -n|--no-logs)
366 no_logs=true
367 ;;
368 -h|--help)
369 help
370 exit 0
371 ;;
372 *)
373 echo "Error: Invalid option: $1" >&2
374 help
375 exit 0
376 ;;
377 esac
378 shift
379 done
380
381 # Check if marzneshin is installed
382 if ! is_marzneshin_installed; then
383 colorized_echo red "Marzneshin's not installed!"
384 exit 1
385 fi
386
387 detect_compose
388
389 down_marzneshin
390 up_marzneshin
391 if [ "$no_logs" = false ]; then
392 follow_marzneshin_logs
393 fi
394}
395
396status_command() {
397
398 # Check if marzneshin is installed
399 if ! is_marzneshin_installed; then
400 echo -n "Status: "
401 colorized_echo red "Not Installed"
402 exit 1
403 fi
404
405 detect_compose
406
407 if ! is_marzneshin_up; then
408 echo -n "Status: "
409 colorized_echo blue "Down"
410 exit 1
411 fi
412
413 echo -n "Status: "
414 colorized_echo green "Up"
415
416 json=$($COMPOSE -f $COMPOSE_FILE ps -a --format=json)
417 services=$(echo "$json" | jq -r 'if type == "array" then .[] else . end | .Service')
418 states=$(echo "$json" | jq -r 'if type == "array" then .[] else . end | .State')
419 # Print out the service names and statuses
420 for i in $(seq 0 $(expr $(echo $services | wc -w) - 1)); do
421 service=$(echo $services | cut -d' ' -f $(expr $i + 1))
422 state=$(echo $states | cut -d' ' -f $(expr $i + 1))
423 echo -n "- $service: "
424 if [ "$state" == "running" ]; then
425 colorized_echo green $state
426 else
427 colorized_echo red $state
428 fi
429 done
430}
431
432logs_command() {
433 help() {
434 colorized_echo red "Usage: marzneshin logs [options]"
435 echo ""
436 echo "OPTIONS:"
437 echo " -h, --help display this help message"
438 echo " -n, --no-follow do not show follow logs"
439 }
440
441 local no_follow=false
442 while [[ "$#" -gt 0 ]]; do
443 case "$1" in
444 -n|--no-follow)
445 no_follow=true
446 ;;
447 -h|--help)
448 help
449 exit 0
450 ;;
451 *)
452 echo "Error: Invalid option: $1" >&2
453 help
454 exit 0
455 ;;
456 esac
457 shift
458 done
459
460 # Check if marzneshin is installed
461 if ! is_marzneshin_installed; then
462 colorized_echo red "Marzneshin is not installed!"
463 exit 1
464 fi
465
466 detect_compose
467
468 if ! is_marzneshin_up; then
469 colorized_echo red "Marzneshin is not up."
470 exit 1
471 fi
472
473 if [ "$no_follow" = true ]; then
474 show_marzneshin_logs
475 else
476 follow_marzneshin_logs
477 fi
478}
479
480cli_command() {
481 # Check if marzneshin is installed
482 if ! is_marzneshin_installed; then
483 colorized_echo red "Marzneshin is not installed!"
484 exit 1
485 fi
486
487 detect_compose
488
489 if ! is_marzneshin_up; then
490 colorized_echo red "Marzneshin is not up."
491 exit 1
492 fi
493
494 marzneshin_cli "$@"
495}
496
497update_command() {
498 check_running_as_root
499 # Check if marzneshin is installed
500 if ! is_marzneshin_installed; then
501 colorized_echo red "Marzneshin is not installed!"
502 exit 1
503 fi
504
505 detect_compose
506
507 update_marzneshin_script
508 colorized_echo blue "Pulling latest version"
509 update_marzneshin
510
511 colorized_echo blue "Restarting Marzneshin's services"
512 down_marzneshin
513 up_marzneshin
514
515 colorized_echo blue "Marzneshin updated successfully"
516}
517
518
519usage() {
520 colorized_echo red "Usage: $0 [command]"
521 echo
522 echo "Commands:"
523 echo " up Start services"
524 echo " down Stop services"
525 echo " restart Restart services"
526 echo " status Show status"
527 echo " logs Show logs"
528 echo " cli Marzneshin command-line interface"
529 echo " install Install Marzneshin"
530 echo " update Update latest version"
531 echo " uninstall Uninstall Marzneshin"
532 echo " install-script Install Marzneshin script"
533 echo
534}
535
536case "$1" in
537 up)
538 shift; up_command "$@";;
539 down)
540 shift; down_command "$@";;
541 restart)
542 shift; restart_command "$@";;
543 status)
544 shift; status_command "$@";;
545 logs)
546 shift; logs_command "$@";;
547 cli)
548 shift; cli_command "$@";;
549 install)
550 shift; install_command "$@";;
551 update)
552 shift; update_command "$@";;
553 uninstall)
554 shift; uninstall_command "$@";;
555 install-script)
556 shift; install_marzneshin_script "$@";;
557 *)
558 usage;;
559esac