-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathnginx_proxy_manager_cli.sh
executable file
·2307 lines (1983 loc) · 85.6 KB
/
nginx_proxy_manager_cli.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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
# Nginx Proxy Manager CLI Script
# Github [ https://github.com/Erreur32/nginx-proxy-manager-Bash-API ]
# By Erreur32 - July 2024
VERSION="2.5.7"
#
# This script allows you to manage Nginx Proxy Manager via the API. It provides
# functionalities such as creating proxy hosts, managing users, listing hosts,
# backing up configurations, and more.
#
# Usage:
# $0 [OPTIONS]
#
# TIPS: Create manually a Config file for persistent variables 'nginx_proxy_manager_cli.conf' :
# With these variables:
# NGINX_IP="127.0.0.1"
# API_USER="[email protected]"
# API_PASS="changeme"
# BASE_DIR="/path/nginx_proxy_script/data"
#
# Examples:
# 📦 Backup First!
# $0 --backup
#
# 🌐 Host Creation:
# $0 -d example.com -i 192.168.1.10 -p 8080 (check default values below)
# $0 --show-default
# $0 --host-list
# $0 --host-ssl-enable 10
#
# 👤 User Creation:
# $0 --create-user newuser password123 [email protected]
# $0 --delete-user 'username'
#
# 🔧 Advanced Example:
# $0 -d example.com -i 192.168.1.10 -p 8080 -a 'proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;'
#
# 🔒 Custom Certificate:
# $0 --generate-cert example.com [email protected]
#
# 📂 Custom locations:
# $0 -d example.com -i 192.168.1.10 -p 8080 -l '[{"path":"/api","forward_host":"192.168.1.11","forward_port":8081}]'
#
# Options:
#
# 🌐 Host proxy creation:
# -d DOMAIN_NAMES Domain name (required for creating/updating hosts)
# -i FORWARD_HOST IP address or domain name of the target server (required for creating/updating hosts)
# -p FORWARD_PORT Port of the target server (required for creating/updating hosts)
# -f FORWARD_SCHEME Scheme for forwarding (http/https, default: http)
# -c CACHING_ENABLED Enable caching (true/false, default: false)
# -b BLOCK_EXPLOITS Block exploits (true/false, default: true)
# -w ALLOW_WEBSOCKET_UPGRADE Allow WebSocket upgrade (true/false, default: true)
# -l CUSTOM_LOCATIONS Custom locations (JSON array of location objects)"
# -a ADVANCED_CONFIG Advanced configuration (block of configuration settings)
#
# 📦 Backup and Restore:
# --backup Backup all configurations to a file
# --backup-host id Backup a single host configuration and its certificate (if exists)
#
# DISABLE
# --restore commands DISABLED , i need to think the best way to do it !!
#
# 🔧 Miscellaneous:
# --check-token Check if the current token is valid
# --create-user user pass email Create a user with a username, password and email
# --delete-user username Delete a user by username
# --host-delete id Delete a proxy host by ID
# --host-show id Show full details for a specific host by ID
# --show-default Show default settings for creating hosts
# --host-list List the names of all proxy hosts
# --host-list-full List all proxy hosts with full details
# --host-list-users List all users
# --host-search hostname Search for a proxy host by domain name
# --host-enable id Enable a proxy host by ID
# --host-disable id Disable a proxy host by ID
# --host-ssl-enable id Enable SSL, HTTP/2, and HSTS for a proxy host
# --host-ssl-disable id Disable SSL, HTTP/2, and HSTS for a proxy host
# --list-ssl-certificates List All SSL certificates availables (JSON)
# --generate-cert domain email Generate certificate for the given domain and email
# --delete-cert domain Delete certificate for the given domain
# --list-access List all available access lists (ID and name)
# --host-acl-enable id,access_list_id Enable ACL for a proxy host by ID with an access list ID
# --host-acl-disable id Disable ACL for a proxy host by ID
# --exemples Display some command exemples
#
# --help Display this help
################################
# Variables to Edit (required) #
# or create a config file #
################################
NGINX_IP="127.0.0.1"
API_USER="user@nginx"
API_PASS="pass nginx"
BASE_DIR="/path/nginx_proxy_script/data"
# Check if config file nginx_proxy_manager_cli.conf exist
SCRIPT_DIR="$(dirname "$0")"
CONFIG_FILE="$SCRIPT_DIR/nginx_proxy_manager_cli.conf"
################################
# PERSISTENT Config
# Create config file $SCRIPT_DIR/nginx_proxy_manager_cli.conf and Variables to Edit (required)
# NGINX_IP="127.0.0.1"
# API_USER="[email protected]"
# API_PASS="changeme"
# BASE_DIR="/path/nginx_proxy_script/dir"
################################
if [ -f "$CONFIG_FILE" ]; then
#echo -e "\n ✅ Loading variables from file $CONFIG_FILE"
# configuration file loading
source "$CONFIG_FILE"
else
echo -e " ⚠️ Configuration file $CONFIG_FILE don't exists. Used Default Variables... "
fi
################################
# Varibles(optionnel debug) #
################################
#echo "NGINX_IP: $NGINX_IP"
#echo "API_USER: $API_USER"
#echo "API_PASS: $API_PASS"
#echo "BASE_DIR: $BASE_DIR"
# API Endpoints
BASE_URL="http://$NGINX_IP:81/api"
API_ENDPOINT="/tokens"
# Directory will be create automatically.
TOKEN_DIR="$BASE_DIR/token"
BACKUP_DIR="$BASE_DIR/backups"
EXPIRY_FILE="$TOKEN_DIR/expiry_${NGINX_IP}.txt"
TOKEN_FILE="$TOKEN_DIR/token_${NGINX_IP}.txt"
# Set Token duration validity.
TOKEN_EXPIRY="365d"
#TOKEN_EXPIRY="31536000s"
#TOKEN_EXPIRY="1y"
# Default variables (you can adapt)
CACHING_ENABLED=false
BLOCK_EXPLOITS=true
ALLOW_WEBSOCKET_UPGRADE=1
HTTP2_SUPPORT=0
ADVANCED_CONFIG=""
LETS_ENCRYPT_AGREE=false
LETS_ENCRYPT_EMAIL=""
FORWARD_SCHEME="http"
FORCE_CERT_CREATION=false
SSL_FORCED=0
HSTS_ENABLED=0
HSTS_SUBDOMAINS=0
# Don't touch below that line (or you know ...)
# Control variables
CREATE_USER=false
DELETE_USER=false
DELETE_HOST=false
LIST_HOSTS=false
LIST_HOSTS_FULL=false
LIST_SSL_CERTIFICATES=false
LIST_USERS=false
INFO=false
UPDATE_FIELD=false
SEARCH_HOST=false
ENABLE_HOST=false
DISABLE_HOST=false
CHECK_TOKEN=false
BACKUP_LIST=false
BACKUP=false
BACKUP_HOST=false
RESTORE=false
RESTORE_HOST=false
GENERATE_CERT=false
ENABLE_SSL=false
DISABLE_SSL=false
HOST_SHOW=false
SHOW_DEFAULT=false
ENABLE_ACL=false
DISABLE_ACL=false
ACCESS_LIST=false
# Colors Custom
COLOR_GREEN="\033[32m"
COLOR_RED="\033[41;1m"
COLOR_ORANGE="\033[38;5;202m"
COLOR_YELLOW="\033[93m"
COLOR_RESET="\033[0m"
COLOR_GREY="\e[90m"
WHITE_ON_GREEN="\033[30;48;5;83m"
###############################################
# Check if necessary dependencies are installed
check_dependencies() {
local dependencies=("curl" "jq")
for dep in "${dependencies[@]}"; do
if ! command -v "$dep" &> /dev/null; then
echo -e "${COLOR_RED}Dependency $dep is not installed. Please install it before running this script.${COLOR_RESET}"
exit 1
fi
done
# Vérification et création des dossiers si nécessaires
if [ ! -d "$BASE_DIR" ]; then
echo -e "\n ${COLOR_RED}Error : BASE_DIR $BASE_DIR Don't exist. Check config.${COLOR_RESET} \n check config variables !"
exit 1
fi
if [ ! -d "$TOKEN_DIR" ]; then
#echo -e "${COLOR_YELLOW}Info : Le dossier de tokens $TOKEN_DIR n'existe pas. Création en cours...${COLOR_RESET}"
mkdir -p "$TOKEN_DIR"
if [ $? -ne 0 ]; then
echo -e "\n ${COLOR_RED}Error: Failed to create token directory $TOKEN_DIR.${COLOR_RESET} \n check config variables !"
exit 1
fi
fi
if [ ! -d "$BACKUP_DIR" ]; then
#echo -e "${COLOR_YELLOW}Info : Le dossier de backups $BACKUP_DIR n'existe pas. Création en cours...${COLOR_RESET}"
mkdir -p "$BACKUP_DIR"
if [ $? -ne 0 ]; then
echo -e "\n ${COLOR_RED}Dependency $dep is not installed. Please install it before running this script.${COLOR_RESET}"
exit 1
fi
fi
}
check_dependencies
# Check if the Nginx Proxy Manager API is accessible
check_nginx_access() {
if ping -c 2 -W 2 $NGINX_IP &> /dev/null; then
if curl --output /dev/null --silent --head --fail "$BASE_URL"; then
echo -e "\n ✅ Nginx url: $BASE_URL"
else
echo -e "\n ⛔ Nginx url ⛔ $BASE_URL is NOT accessible."
exit 1
fi
else
echo -e "\n ⛔ $NGINX_IP ⛔ is not responding. Houston, we have a problem."
exit 1
fi
}
# check_nginx_access
# !!! ne filtrer que les dossiers !
# Function to list available backups
list_backups() {
echo "Available backups:"
for domain in $(ls -td "$BACKUP_DIR"/*/); do
domain_name=$(basename "$domain")
echo " - ${domain_name//_/.}"
done
}
# Display help
usage() {
echo -e "Options:"
echo -e " -d ${COLOR_ORANGE}DOMAIN_NAMES${COLOR_RESET} Domain name (${COLOR_RED}required${COLOR_RESET})"
echo -e " -i ${COLOR_ORANGE}FORWARD_HOST${COLOR_RESET} IP address or domain name of the target server (${COLOR_RED}required${COLOR_RESET})"
echo -e " -p ${COLOR_ORANGE}FORWARD_PORT${COLOR_RESET} Port of the target server (${COLOR_RED}required${COLOR_RESET})"
echo -e "\n (Check default settings,no argument needed if already set!)"
echo -e " -f FORWARD_SCHEME Scheme for forwarding (http/https, default: $(colorize_booleanh $FORWARD_SCHEME))"
echo -e " -c CACHING_ENABLED Enable caching (true/false, default: $(colorize_boolean $CACHING_ENABLED))"
echo -e " -b BLOCK_EXPLOITS Block exploits (true/false, default: $(colorize_boolean $BLOCK_EXPLOITS))"
echo -e " -w ALLOW_WEBSOCKET_UPGRADE Allow WebSocket upgrade (true/false, default: $(colorize_boolean $ALLOW_WEBSOCKET_UPGRADE))"
echo -e " -l CUSTOM_LOCATIONS Custom locations (${COLOR_YELLOW}JSON array${COLOR_RESET} of location objects)"
echo -e " -a ADVANCED_CONFIG Advanced configuration (${COLOR_YELLOW}string${COLOR_RESET})"
echo ""
echo -e " --info ℹ️ ${COLOR_YELLOW}Display${COLOR_RESET} Script Variables Information"
echo -e " --show-default 🔍 ${COLOR_YELLOW}Show${COLOR_RESET} Default settings for creating hosts"
echo -e " --backup 📦 ${COLOR_GREEN}Backup${COLOR_RESET} All configurations to a different files in \$BACKUP_DIR"
echo -e " --backup-host id 📦 ${COLOR_GREEN}Backup${COLOR_RESET} Single host configuration and its certificate (if exists)"
#echo -e " --restore 📦 ${COLOR_GREEN}Restore${COLOR_RESET} All configurations from a backup file"
#echo -e " --restore-host id 📦 ${COLOR_GREEN}Restore${COLOR_RESET} Restore single host with list with empty arguments or a Domain name"
echo -e " --check-token 🔧 ${COLOR_YELLOW}Check${COLOR_RESET} If the current token is valid"
echo -e " --create-user user pass email 👤 ${COLOR_GREEN}Create${COLOR_RESET} User with a ${COLOR_YELLOW}username, ${COLOR_YELLOW}password${COLOR_RESET} and ${COLOR_YELLOW}email${COLOR_RESET}"
echo -e " --delete-user username 💣 ${COLOR_ORANGE}Delete${COLOR_RESET} User by ${COLOR_YELLOW}username${COLOR_RESET}"
echo -e " --host-delete id 💣 ${COLOR_ORANGE}Delete${COLOR_RESET} Proxy host by ${COLOR_YELLOW}ID${COLOR_RESET}"
echo -e " --host-search hostname 🔍 ${COLOR_GREEN}Search${COLOR_RESET} Proxy host by domain name"
echo -e " --host-show id 🔍 ${COLOR_YELLOW}Show${COLOR_RESET} Full details for a specific host by ${COLOR_YELLOW}ID${COLOR_RESET}"
echo -e " --host-list 📋 ${COLOR_YELLOW}List${COLOR_RESET} All Proxy hosts (table form)"
echo -e " --host-list-full 📋 ${COLOR_YELLOW}List${COLOR_RESET} All Proxy hosts full details (JSON)"
echo -e " --host-list-users 📋 ${COLOR_YELLOW}List${COLOR_RESET} All Users"
echo -e " --host-enable id ✅ ${COLOR_GREEN}Enable${COLOR_RESET} Proxy host by ${COLOR_YELLOW}ID${COLOR_RESET}"
echo -e " --host-disable id ❌ ${COLOR_ORANGE}Disable${COLOR_RESET} Proxy host by ${COLOR_YELLOW}ID${COLOR_RESET}"
echo -e " --access-list 📋 ${COLOR_YELLOW}List${COLOR_RESET} All available Access Lists (ID and Name)"
echo -e " --host-acl-enable id,access_list_id ✅ ${COLOR_GREEN}Enable ACL${COLOR_RESET} for Proxy host by ${COLOR_YELLOW}ID${COLOR_RESET} with Access List ID (e.g., --host-acl-enable 16,2)"
echo -e " --host-acl-disable id ❌ ${COLOR_ORANGE}Disable ACL${COLOR_RESET} for Proxy host by ${COLOR_YELLOW}ID${COLOR_RESET}"
echo -e " --host-ssl-enable id 🔒 ${COLOR_GREEN}Enable${COLOR_RESET} SSL, HTTP/2, and HSTS for a proxy host (Enabled only if exist, check ${COLOR_ORANGE}--generate-cert${COLOR_RESET} to creating one)"
echo -e " --host-ssl-disable id 🔓 ${COLOR_ORANGE}Disable${COLOR_RESET} SSL, HTTP/2, and HSTS for a proxy host"
echo -e " --list-ssl-certificates [domain] 📋 ${COLOR_YELLOW}List${COLOR_RESET} All SSL certificates availables or filtered by [domain name] (JSON)"
echo -e " --generate-cert domain email 🌀 ${COLOR_GREEN}Generate${COLOR_RESET} Certificate for the given '${COLOR_YELLOW}domain${COLOR_RESET}' and '${COLOR_YELLOW}email${COLOR_RESET}'"
echo -e " --delete-cert domain 💣 ${COLOR_ORANGE}Delete${COLOR_RESET} Certificate for the given '${COLOR_YELLOW}domain${COLOR_RESET}' "
echo -e " --update-host id field=value 🔄 ${COLOR_GREEN}Update${COLOR_RESET} a specific field of an existing proxy host by ${COLOR_YELLOW}ID${COLOR_RESET} (e.g., --update-host 42 forward_host=foobar.local)"
echo -e " --examples 🔖 Examples commands, more explicits"
echo -e " --help 👉 It's me"
echo ""
exit 0
}
# Examples CLI Commands
examples_cli() {
echo -e "\n${COLOR_YELLOW}Usage: $0 -d domain -i ip -p port [-f forward_scheme] [-c caching_enabled] [-b block_exploits] [-w allow_websocket_upgrade] [-a advanced_config] [-t token_expiry] [--create-user username password email] [--delete-user username] [--host-delete id] [--host-list] [--host-list-full] [--host-list-certificates] [--host-list-users] [--host-search hostname] [--host-enable id] [--host-disable id] [--check-token] [--backup] [--backup-host id] [--restore] [--restore-host id] [--generate-cert domain email [--custom]] [--host-ssl-enable id] [--host-ssl-disable id] [--host-show id] [--show-default] [--help]${COLOR_RESET}"
echo -e ""
echo -e "Examples:"
echo -e "\n 📋 List host"
echo -e "${COLOR_GREY} $0 --host-list${COLOR_RESET}"
echo -e "\n 📦 Backup First before doing anything!${COLOR_GREY}"
echo -e " $0 --backup"
echo -e " $0 --backup-host 1"
# echo -e " $0 --restore"
# echo -e " $0 --restore-host 1"
echo -e "\n ${COLOR_RESET}🌐 Host Creation${COLOR_GREY}"
echo -e " $0 --show-default"
echo -e " $0 -d example.com -i 192.168.1.10 -p 8080"
echo -e " $0 --host-ssl-enable 10"
echo -e " $0 --host-show 10"
echo -e " $0 --host-list"
echo -e "\n $0 --list-ssl-certificates domain.com"
echo -e "\n ${COLOR_RESET}👤 User Management${COLOR_GREY}"
echo -e " $0 --create-user newuser password123 [email protected]"
echo -e " $0 --delete-user 'username'"
echo -e "\n ${COLOR_RESET}🔧 Advanced Example:${COLOR_GREY}"
echo -e " $0 -d example.com -i 192.168.1.10 -p 8080 -a 'proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;'"
echo -e " $0 --generate-cert example.com [email protected] --custom"
echo -e "\n ${COLOR_RESET}📁 Custom locations:${COLOR_GREY}"
echo -e " $0 -d example.com -i 192.168.1.10 -p 8080 -l '[{\"path\":\"/api\",\"forward_host\":\"192.168.1.11\",\"forward_port\":8081}]'"
echo -e "\n ${COLOR_RESET}🔖 Full option:${COLOR_GREY}"
echo -e " $0 -d example.com -i 192.168.1.10 -p 8080 -f https -c true -b true -w true -a 'proxy_set_header X-Real-IP \$remote_addr;' -l '[{\"path\":\"/api\",\"forward_host\":\"192.168.1.11\",\"forward_port\":8081}]'"
echo -e "${COLOR_RESET}"
echo ""
exit 0
}
# Display script variables info
display_info() {
check_dependencies
check_nginx_access
echo -e "\n${COLOR_YELLOW}Script Info: ${COLOR_GREEN}${VERSION}${COLOR_RESET}"
echo -e "\n${COLOR_YELLOW}Script Variables Information:${COLOR_RESET}"
echo -e " ${COLOR_GREEN}BASE_DIR${COLOR_RESET} ${BASE_DIR}"
echo -e " ${COLOR_YELLOW}Config${COLOR_RESET} ${BASE_DIR}/nginx_proxy_manager_cli.conf"
echo -e " ${COLOR_GREEN}BASE_URL${COLOR_RESET} ${BASE_URL}"
echo -e " ${COLOR_GREEN}NGINX_IP${COLOR_RESET} ${NGINX_IP}"
echo -e " ${COLOR_GREEN}API_USER${COLOR_RESET} ${API_USER}"
echo -e " ${COLOR_GREEN}BACKUP_DIR${COLOR_RESET} ${BACKUP_DIR}"
if [ -d "$BACKUP_DIR" ]; then
backup_count=$(ls -1 "$BACKUP_DIR" | wc -l)
echo -e " ${COLOR_GREEN}BACKUP HOST ${COLOR_YELLOW}$backup_count ${COLOR_RESET}"
else
echo -e " ${COLOR_RED}Backup directory does not exist.${COLOR_RESET}"
fi
if [ -f "$TOKEN_FILE" ]; then
echo -e " ${COLOR_GREEN}Token NPM ${COLOR_YELLOW} $TOKEN_FILE ${COLOR_RESET}"
else
echo -e "\n ${COLOR_RED}Generating new token... ${COLOR_RESET}"
# check if empty file
if [ ! -s "$TOKEN_FILE" ]; then
echo -e " Create $TOKEN_DIR"
rm -rf "$TOKEN_DIR"
mkdir "$TOKEN_DIR"
else
echo -e " File $TOKEN_FILE ✅"
fi
echo -e "\n 🔖 Check token 🆔\n"
generate_token
#validate_token
fi
echo -e "\n --help (Show all commands)"
}
# shellcheck disable=SC2120
# check_no_arguments() {
# if [ $# -eq 0 ]; then
# echo -e "\n ${COLOR_RED}No arguments provided. Use --help to see all command options.${COLOR_RESET}"
# echo ""
# #display_info
# exit 1
# fi
# }
# Colorize boolean values for display
colorize_boolean() {
local value=$1
if [ "$value" = true ]; then
echo -e "${COLOR_GREEN}true${COLOR_RESET}"
else
echo -e "${COLOR_YELLOW}false${COLOR_RESET}"
fi
}
colorize_booleanh() {
local value=$1
if [ "$value" = https ]; then
echo -e "${COLOR_GREEN}https${COLOR_RESET}"
else
echo -e "${COLOR_YELLOW}http${COLOR_RESET}"
fi
}
################################
# Generate a new API token
generate_token() {
# response=$(curl -s -X POST "$BASE_URL$API_ENDPOINT?expiresIn=$TOKEN_EXPIRY" \
response=$(curl -s -X POST "$BASE_URL$API_ENDPOINT?expiry=$TOKEN_EXPIRY" \
-H "Content-Type: application/json; charset=UTF-8" \
--data-raw "{\"identity\":\"$API_USER\",\"secret\":\"$API_PASS\"}")
# Old way
# response=$(curl -s -X POST "$BASE_URL$API_ENDPOINT" \
# -H "Content-Type: application/json; charset=UTF-8" \
# --data-raw "{\"identity\":\"$API_USER\",\"secret\":\"$API_PASS\",\"expiry\":\"$TOKEN_EXPIRY\"}")
token=$(echo "$response" | jq -r '.token')
expires=$(echo "$response" | jq -r '.expires')
## Debug
# echo "Request URL: $BASE_URL$API_ENDPOINT?expiry=$TOKEN_EXPIRY"
# echo "Request Body: {\"identity\":\"$API_USER\",\"secret\":\"$API_PASS\"}"
# echo "Response: $response"
##
if [ "$token" != "null" ]; then
echo "$token" > $TOKEN_FILE
echo "$expires" > $EXPIRY_FILE
echo " Token 🆔: $token"
echo " Expiry : $expires"
echo -e "\n ✅ ${COLOR_GREEN}The token is valid. Expiry: $expires${COLOR_RESET}"
else
echo -e " ${COLOR_RED}Error generating token.${COLOR_RESET}"
echo -e " Check your credentials."
exit 1
fi
}
renew_token_if_needed() {
#CHECK_TOKEN=true
if [ ! -f "$TOKEN_FILE" ] || [ ! -f "$EXPIRY_FILE" ]; then
return 1
fi
token=$(cat $TOKEN_FILE)
expires=$(cat $EXPIRY_FILE)
current_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
if [[ "$current_time" < "$expires" ]]; then
echo -e "\n ✅ ${COLOR_GREEN}The token is valid. Expiry: $expires${COLOR_RESET}"
return 0
else
echo -e "\n ⛔ ${COLOR_RED}The token is invalid. Expiry: $expires${COLOR_RESET}"
generate_token
return 1
fi
}
# Validate the existing token
validate_token() {
if [ ! -f "$TOKEN_FILE" ] || [ ! -f "$EXPIRY_FILE" ]; then
echo -e "\n ⛔ ${COLOR_RED}No valid token found. Generating a new token...${COLOR_RESET}"
generate_token
fi
expires=$(cat $EXPIRY_FILE)
current_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
if [[ "$current_time" < "$expires" ]]; then
echo -e " ✅ ${COLOR_GREEN}The token is valid. Expiry: $expires${COLOR_RESET}"
# return 0
else
echo -e " ⛔ ${COLOR_RED}The token is invalid. Expiry: $expires${COLOR_RESET}"
echo -e " 🔄 ${COLOR_GREEN}Processing NEW Token${COLOR_RESET}\n"
generate_token
# return 1
fi
}
#################################
while getopts "d:i:p:f:c:b:w:a:l:-:" opt; do
case $opt in
d) DOMAIN_NAMES="$OPTARG" ;;
i) FORWARD_HOST="$OPTARG" ;;
p) FORWARD_PORT="$OPTARG" ;;
f) FORWARD_SCHEME="$OPTARG" ;;
c) CACHING_ENABLED="$OPTARG" ;;
b) BLOCK_EXPLOITS="$OPTARG" ;;
w) ALLOW_WEBSOCKET_UPGRADE="$OPTARG" ;;
a) ADVANCED_CONFIG="$OPTARG" ;;
l) CUSTOM_LOCATIONS="$OPTARG" ;;
-)
case "${OPTARG}" in
show-default) SHOW_DEFAULT=true ;;
backup) BACKUP=true ;;
backup-host)
validate_token
BACKUP_HOST=true
HOST_ID="${!OPTIND}"; shift
;;
backup-list) BACKUP_LIST=true ;;
restore-host)
if [ -n "${!OPTIND}" ] && [[ "${!OPTIND}" != -* ]]; then
RESTORE_HOST=true
DOMAIN="${!OPTIND}"; shift
else
list_backups
echo -n "Enter domain to restore: "
read DOMAIN
RESTORE_HOST=true
fi
;;
ssl-regenerate) validate_token; SSL_REGENERATE=true ;;
ssl-restore) validate_token; SSL_RESTORE=true ;;
create-user)
validate_token
CREATE_USER=true
USERNAME="${!OPTIND}"; shift
PASSWORD="${!OPTIND}"; shift
EMAIL="${!OPTIND}"; shift
;;
delete-user)
validate_token
DELETE_USER=true
USERNAME="${!OPTIND}"; shift
;;
host-delete)
validate_token
DELETE_HOST=true
HOST_ID="${!OPTIND}"; shift
;;
host-show)
validate_token
HOST_SHOW=true
HOST_ID="${!OPTIND}"; shift
;;
host-list) validate_token; LIST_HOSTS=true ;;
host-list-full) validate_token; LIST_HOSTS_FULL=true ;;
host-list-users) validate_token; LIST_USERS=true ;;
host-search)
validate_token
SEARCH_HOST=true
SEARCH_HOSTNAME="${!OPTIND}"; shift
;;
host-enable)
validate_token
ENABLE_HOST=true
HOST_ID="${!OPTIND}"; shift
;;
host-disable)
validate_token
DISABLE_HOST=true
HOST_ID="${!OPTIND}"; shift
;;
host-acl-enable)
validate_token
ENABLE_ACL=true
# Expecting "HOST_ID,ACCESS_LIST_ID"
ACL_ARG="${!OPTIND}"; shift
IFS=',' read -r HOST_ID ACCESS_LIST_ID <<< "$ACL_ARG"
if [ -z "$HOST_ID" ] || [ -z "$ACCESS_LIST_ID" ]; then
echo -e "\n ⛔ ${COLOR_RED}Erreur : --host-acl-enable need HOST_ID et ACCESS_LIST_ID separated by a comma (e.g., --host-acl-enable 16,2).${COLOR_RESET}"
usage
fi
;;
host-acl-disable)
validate_token
DISABLE_ACL=true
HOST_ID="${!OPTIND}"; shift
;;
check-token) CHECK_TOKEN=true ;;
generate-cert)
validate_token
GENERATE_CERT=true
DOMAIN="${!OPTIND}"; shift
EMAIL="${!OPTIND}"; shift
;;
delete-cert)
validate_token
DELETE_CERT=true
DOMAIN="${!OPTIND}"; shift
;;
host-ssl-enable)
validate_token
ENABLE_SSL=true
HOST_ID="${!OPTIND}"; shift
# Check if HOST_ID is provided
if [ -z "$HOST_ID" ]; then
echo -e " \n⛔ ${COLOR_RED}Error: Missing host ID for --host-ssl-enable.${COLOR_RESET}"
echo -e " To find ID Check with ${COLOR_ORANGE}$0 --host-list${COLOR_RESET}\n"
exit 1
fi
;;
host-ssl-disable)
validate_token
DISABLE_SSL=true
HOST_ID="${!OPTIND}"; shift
;;
force-cert-creation)
validate_token
FORCE_CERT_CREATION=true ;;
list-ssl-certificates)
validate_token
LIST_SSL_CERTIFICATES=true
DOMAIN="$2"
#DOMAIN="${!OPTIND}"; shift
;;
access-list) validate_token; ACCESS_LIST=true ;;
update-host)
validate_token
UPDATE_FIELD=true
HOST_ID="${!OPTIND}"; shift
FIELD_VALUE="${!OPTIND}"; shift
FIELD=$(echo "$FIELD_VALUE" | cut -d= -f1)
VALUE=$(echo "$FIELD_VALUE" | cut -d= -f2-)
;;
examples) EXAMPLES=true ;;
info) INFO=true ;;
esac ;;
*) INFO=true # display_info; exit 0
;;
esac
done
# If no arguments are provided, display usage
if [ $# -eq 0 ]; then
#echo -e "\n Unknown option --${OPTARG}" ;
display_info
# usage
exit 0
fi
################################
# DEBUG
debug_var(){
# 🔍 Debugging Data
echo -e "\n 🔍 Debugging variables before JSON update:"
echo " DOMAIN_NAMES: $DOMAIN_NAMES"
echo " FORWARD_HOST: $FORWARD_HOST"
echo " FORWARD_PORT: $FORWARD_PORT"
echo " FORWARD_SCHEME: $FORWARD_SCHEME"
echo " CACHING_ENABLED: $CACHING_ENABLED_JSON"
echo " BLOCK_EXPLOITS: $BLOCK_EXPLOITS_JSON"
echo " ALLOW_WEBSOCKET_UPGRADE: $ALLOW_WEBSOCKET_UPGRADE_JSON"
echo " HTTP2_SUPPORT: $HTTP2_SUPPORT_JSON"
echo " CUSTOM_LOCATIONS: $CUSTOM_LOCATIONS_ESCAPED"
echo " ADVANCED_CONFIG: $ADVANCED_CONFIG"
}
######################################
list_access() {
echo -e " \n Available Access Lists:"
RESPONSE=$(curl -s -X GET "$BASE_URL/nginx/access-lists" \
-H "Authorization: Bearer $(cat $TOKEN_FILE)")
# Check if the response is a valid JSON array
if echo " $RESPONSE" | jq -e 'type == "array"' > /dev/null; then
# Loop through and display the elements of the list
echo -e "${COLOR_YELLOW}"
echo " $RESPONSE" | jq -r '.[] | " \(.id): \(.name)"'
echo -e "${COLOR_RESET}"
else
# In case of an error, check if there is an error message in the response
if echo " $RESPONSE" | jq -e '.error // empty' > /dev/null; then
echo -e " ⛔ API Error: $(echo "$RESPONSE" | jq -r '.message')"
else
echo -e " ⛔ Unknown Error: $RESPONSE"
fi
fi
}
################################
# ACL proxy host
enable_acl() {
if [ -z "$HOST_ID" ] || [ -z "$ACCESS_LIST_ID" ]; then
echo -e "\n ⛔ ${COLOR_RED}Error: HOST_ID and ACCESS_LIST_ID are required to enable the ACL.${COLOR_RESET}"
usage
fi
echo -e " 🔓 Enabling ACL for host ID: $HOST_ID with access list ID: $ACCESS_LIST_ID..."
DATA=$(jq -n \
--argjson access_list_id "$ACCESS_LIST_ID" \
--argjson enabled true \
'{
access_list_id: $access_list_id,
enabled: $enabled
}')
RESPONSE=$(curl -s -X PUT "$BASE_URL/nginx/proxy-hosts/$HOST_ID" \
-H "Authorization: Bearer $(cat $TOKEN_FILE)" \
-H "Content-Type: application/json; charset=UTF-8" \
--data-raw "$DATA")
if [ "$(echo "$RESPONSE" | jq -r '.error | length')" -eq 0 ]; then
echo -e " ✅ ${COLOR_GREEN}ACL successfully enabled for host ID $HOST_ID!${COLOR_RESET}"
else
echo -e " ⛔ ${COLOR_RED}Failed to enable ACL. Error: $(echo "$RESPONSE" | jq -r '.message')${COLOR_RESET}\n"
fi
}
# Disable ACL for a given proxy host
disable_acl() {
if [ -z "$HOST_ID" ]; then
echo -e "\n ⛔ ${COLOR_RED}Error: HOST_ID is required to disable the ACL.${COLOR_RESET}"
usage
fi
echo -e " 🔒 Disabling ACL for host ID: $HOST_ID..."
DATA=$(jq -n \
--argjson access_list_id null \
--argjson enabled false \
'{
access_list_id: $access_list_id,
enabled: $enabled
}')
RESPONSE=$(curl -s -X PUT "$BASE_URL/nginx/proxy-hosts/$HOST_ID" \
-H "Authorization: Bearer $(cat $TOKEN_FILE)" \
-H "Content-Type: application/json; charset=UTF-8" \
--data-raw "$DATA")
if [ "$(echo "$RESPONSE" | jq -r '.error | length')" -eq 0 ]; then
echo -e " ✅ ${COLOR_GREEN}ACL successfully disabled for host ID $HOST_ID!${COLOR_RESET}"
else
echo -e " ⛔ ${COLOR_RED}Failed to disable ACL. Error: $(echo "$RESPONSE" | jq -r '.message')${COLOR_RESET}\n"
fi
}
# Function to check if the host ID exists
host-check-id() {
local host_id=$1
# shellcheck disable=SC2155
local host_list=$($0 --host-list)
if echo "$host_list" | grep -q ""id": $host_id"; then
return 0
else
echo "Error: Host ID $host_id does not exist."
exit 1
fi
}
######################################
# Function to validate JSON files
validate_json() {
local file=$1
if ! jq empty "$file" 2>/dev/null; then
echo -e "\n ⛔ Invalid JSON detected in file: $file"
cat "$file" # Afficher le contenu du fichier pour debug
return 1
fi
return 0
}
######################################
# Function to regenerate SSL certificates for all hosts
regenerate_all_ssl_certificates() {
echo -e "\n🔄 Regenerating SSL certificates for all hosts..."
# shellcheck disable=SC2155
local hosts=$(curl -s -X GET -H "Authorization: Bearer $TOKEN" "$NGINX_API_URL/nginx/proxy-hosts")
# shellcheck disable=SC2207
local host_ids=($(echo "$hosts" | jq -r '.[] | select(.ssl.enabled == true) | .id'))
if [ ${#host_ids[@]} -eq 0 ]; then
echo " ⛔ No hosts with SSL certificates found."
return 1
fi
for host_id in "${host_ids[@]}"; do
echo -e "\n🔄 Regenerating SSL certificate for host ID: $host_id"
local response=$(curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"id":'"$host_id"',"provider":"letsencrypt"}' "$NGINX_API_URL/nginx/certificates/generate")
if [[ $response == *"error"* ]]; then
echo -e " ⛔ Error regenerating SSL certificate for host ID: $host_id: $response"
else
echo -e " ✅ SSL certificate regenerated for host ID: $host_id"
fi
done
}
##############################################################
# Function to delete all existing proxy hosts
delete_all_proxy_hosts() {
echo -e "\n 🗑️ ${COLOR_ORANGE}Deleting all existing proxy hosts...${COLOR_RESET}"
existing_hosts=$(curl -s -X GET "$BASE_URL/nginx/proxy-hosts" \
-H "Authorization: Bearer $(cat $TOKEN_FILE)" | jq -r '.[].id')
for host_id in $existing_hosts; do
echo -e " 💣 Deleting host ID $host_id..."
response=$(curl -s -w "HTTPSTATUS:%{http_code}" -X DELETE "$BASE_URL/nginx/proxy-hosts/$host_id" \
-H "Authorization: Bearer $(cat $TOKEN_FILE)")
http_body=$(echo "$response" | sed -e 's/HTTPSTATUS\:.*//g')
http_status=$(echo "$response" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
if [ "$http_status" -ne 200 ]; then
echo -e " ⛔ ${COLOR_RED}Failed to delete host ID $host_id. HTTP status: $http_status. Response: $http_body${COLOR_RESET}"
return 1
fi
done
echo -e " ✅ ${COLOR_GREEN}All existing proxy hosts deleted successfully!${COLOR_RESET}"
return 0
}
##############################################################
# Delete a proxy host by ID
delete_proxy_host() {
if [ -z "$HOST_ID" ]; then
echo -e "\n 💣 The --host-delete option requires a host ID."
usage
fi
echo -e " 💣 Deleting proxy host ID: $HOST_ID..."
RESPONSE=$(curl -s -w "HTTPSTATUS:%{http_code}" -X DELETE "$BASE_URL/nginx/proxy-hosts/$HOST_ID" \
-H "Authorization: Bearer $(cat $TOKEN_FILE)")
HTTP_BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
HTTP_STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
if ! [[ "$HTTP_STATUS" =~ ^[0-9]+$ ]] || [ "$HTTP_STATUS" -ne 200 ]; then
echo -e " ⛔ ${COLOR_RED}Failed to delete proxy host. HTTP status: $HTTP_STATUS. Error: $HTTP_BODY${COLOR_RESET}"
return 1
else
echo -e " ✅ ${COLOR_GREEN}Proxy host 💣 deleted successfully!${COLOR_RESET}\n"
return 0
fi
}
################################
# Check if a proxy host with the given domain names already exists
check_existing_proxy_host() {
echo -e "\n 🔎 Checking if proxy host $DOMAIN_NAMES already exists..."
RESPONSE=$(curl -s -X GET "$BASE_URL/nginx/proxy-hosts" \
-H "Authorization: Bearer $(cat $TOKEN_FILE)")
# echo -e "\n 🔍 Raw API Response: $RESPONSE" # Debugging API response
EXISTING_HOST=$(echo "$RESPONSE" | jq -r --arg DOMAIN "$DOMAIN_NAMES" '.[] | select(.domain_names[] == $DOMAIN)')
if [ -n "$EXISTING_HOST" ]; then
echo -e "\n 🔔 Proxy host for $DOMAIN_NAMES already exists."
read -p " 👉 Do you want to update it? (y/n): " -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
HOST_ID=$(echo "$EXISTING_HOST" | jq -r '.id')
update_proxy_host "$HOST_ID"
else
echo -e " ${COLOR_YELLOW}🚫 No changes made.${COLOR_RESET}"
exit 0
fi
else
create_new_proxy_host
fi
}
################################
# Update an existing proxy host
update_proxy_host() {
HOST_ID=$1
echo -e "\n 🔄 Updating proxy host for $DOMAIN_NAMES..."
# 🔥 Vérifier que les variables obligatoires sont bien définies
if [ -z "$DOMAIN_NAMES" ] || [ -z "$FORWARD_HOST" ] || [ -z "$FORWARD_PORT" ] || [ -z "$FORWARD_SCHEME" ]; then
echo -e " ⛔${COLOR_RED} ERROR: Missing required parameters (domain, forward host, forward port, forward scheme).${COLOR_RESET}"
exit 1
fi
# 🔥 Vérifier que FORWARD_PORT est un nombre valide
if ! [[ "$FORWARD_PORT" =~ ^[0-9]+$ ]]; then
echo -e " ⛔${COLOR_RED} ERROR: FORWARD_PORT is not a number! Value: '$FORWARD_PORT'${COLOR_RESET}"
exit 1
fi
# 🔥 Correction : S'assurer que `CUSTOM_LOCATIONS` est toujours un JSON valide
if [[ -z "$CUSTOM_LOCATIONS" || "$CUSTOM_LOCATIONS" == "null" ]]; then
CUSTOM_LOCATIONS_ESCAPED="[]"
else
CUSTOM_LOCATIONS_ESCAPED=$(echo "$CUSTOM_LOCATIONS" | jq -c . 2>/dev/null || echo '[]')
fi
# Correction des booléens (true / false en JSON)
CACHING_ENABLED_JSON=$( [ "$CACHING_ENABLED" == "true" ] && echo true || echo false )
BLOCK_EXPLOITS_JSON=$( [ "$BLOCK_EXPLOITS" == "true" ] && echo true || echo false )
ALLOW_WEBSOCKET_UPGRADE_JSON=$( [ "$ALLOW_WEBSOCKET_UPGRADE" == "true" ] && echo true || echo false )
HTTP2_SUPPORT_JSON=$( [ "$HTTP2_SUPPORT" == "true" ] && echo true || echo false )
# 🔍 Debugging variables before JSON update:
debug_var
# 🔥 Générer le JSON proprement
DATA=$(jq -n \
--arg domain "$DOMAIN_NAMES" \
--arg host "$FORWARD_HOST" \
--arg port "$FORWARD_PORT" \
--arg scheme "$FORWARD_SCHEME" \
--argjson caching "$CACHING_ENABLED_JSON" \
--argjson block_exploits "$BLOCK_EXPLOITS_JSON" \
--arg advanced_config "$ADVANCED_CONFIG" \
--argjson websocket_upgrade "$ALLOW_WEBSOCKET_UPGRADE_JSON" \
--argjson http2_support "$HTTP2_SUPPORT_JSON" \
--argjson enabled true \
--argjson locations "$CUSTOM_LOCATIONS_ESCAPED" \
'{
domain_names: [$domain],
forward_host: $host,
forward_port: ($port | tonumber),
access_list_id: null,
certificate_id: null,
ssl_forced: false,
caching_enabled: $caching,
block_exploits: $block_exploits,
advanced_config: $advanced_config,
meta: { dns_challenge: null },
allow_websocket_upgrade: $websocket_upgrade,
http2_support: $http2_support,
forward_scheme: $scheme,
enabled: $enabled,
locations: $locations
}'
)
# 🔍 Vérifier si le JSON est valide avant l'envoi
if ! echo "$DATA" | jq empty > /dev/null 2>&1; then
echo -e " ⛔${COLOR_RED} ERROR: Invalid JSON generated:\n$DATA ${COLOR_RESET}"
exit 1
fi
# 🚀 Envoyer la requête API pour mise à jour
RESPONSE=$(curl -s -X PUT "$BASE_URL/nginx/proxy-hosts/$HOST_ID" \
-H "Authorization: Bearer $(cat $TOKEN_FILE)" \
-H "Content-Type: application/json; charset=UTF-8" \
--data-raw "$DATA")
# 📢 Vérifier la réponse de l'API
ERROR_MSG=$(echo "$RESPONSE" | jq -r '.error.message // empty')
if [ -z "$ERROR_MSG" ]; then
echo -e "\n ✅ ${COLOR_GREEN}SUCCESS: Proxy host 🔗$DOMAIN_NAMES updated successfully! 🎉${COLOR_RESET}"
else
echo -e " ⛔ ${COLOR_RED}Failed to update proxy host. Error: $ERROR_MSG ${COLOR_RESET}"
exit 1
fi
}
###########################
# Create a new proxy host
create_new_proxy_host() {
echo -e "\n 🌍 Creating proxy host for $DOMAIN_NAMES..."
# Vérifier que les variables obligatoires sont bien définies
if [ -z "$DOMAIN_NAMES" ] || [ -z "$FORWARD_HOST" ] || [ -z "$FORWARD_PORT" ] || [ -z "$FORWARD_SCHEME" ]; then
echo -e " ⛔${COLOR_RED} ERROR: Missing required parameters ${COLOR_RESET}(domain, forward host, forward port, forward scheme)."
exit 1
fi
# Vérifier que FORWARD_PORT est bien un nombre
if ! [[ "$FORWARD_PORT" =~ ^[0-9]+$ ]]; then