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