-
Notifications
You must be signed in to change notification settings - Fork 56
/
Copy pathinstall.sh
747 lines (654 loc) · 26.7 KB
/
install.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
#!/bin/bash
output(){
echo -e '\e[36m'$1'\e[0m';
}
PANEL=latest
WINGS=latest
preflight(){
output "Pterodactyl Installation & Upgrade Script"
output "Copyright © 2018-2023 Thien Tran <[email protected]>."
output "Please join my Matrix for community support: https://matrix.to/#/#tommy:arcticfoxes.net"
output ""
output "Please note that this script is meant to do installations on a fresh OS."
if [ "$EUID" -ne 0 ]; then
output "Please run as root."
exit 3
fi
if [ -r /etc/os-release ]; then
lsb_dist="$(. /etc/os-release && echo "$ID")"
dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
if [ "$lsb_dist" = "rhel" ] || [ "$lsb_dist" = "rocky" ] || [ "$lsb_dist" = "almalinux" ]; then
dist_version="$(echo $dist_version | awk -F. '{print $1}')"
fi
else
exit 1
fi
if [ "$lsb_dist" = "rhel" ]; then
if [ $dist_version != "9" ]; then
output "Unsupported RHEL version. Only RHEL 9 is supported."
exit 2
fi
elif [ "$lsb_dist" = "centos" ]; then
if [ "$dist_version" != "9" ]; then
output "Unsupported CentOS version. Only CentOS Stream 9 is supported."
exit 2
fi
elif [ "$lsb_dist" = "rocky" ]; then
if [ "$dist_version" != "9" ]; then
output "Unsupported Rocky Linux version. Only Rocky Linux 9 is supported."
exit 2
fi
elif [ "$lsb_dist" = "almalinux" ]; then
if [ "$dist_version" != "9" ]; then
output "Unsupported AlmaLinux version. Only AlmaLinux 9 is supported."
exit 2
fi
elif [ "$lsb_dist" != "rhel" ] && [ "$lsb_dist" != "centos" ] && [ "$lsb_dist" != "rocky" ] && [ "$lsb_dist" != "almalinux" ]; then
output "Unsupported operating system."
output ""
output "Supported OS:"
output "RHEL: 9"
output "CentOS Stream: 9"
output "Rocky Linux: 9"
output "AlmaLinux: 9"
exit 2
fi
}
install_options(){
output "Please select your installation option:"
output "[1] Install the panel ${PANEL}."
output "[2] Install the wings ${WINGS}."
output "[3] Install the panel ${PANEL} and wings ${WINGS}."
output "[4] Upgrade panel to ${PANEL}."
output "[5] Upgrade wings to ${WINGS}."
output "[6] Upgrade panel to ${PANEL} and daemon to ${WINGS}."
output "[7] Emergency MariaDB root password reset."
output "[8] Emergency database host information reset."
read -r choice
case $choice in
1 ) installoption=1
output "You have selected ${PANEL} panel installation only."
;;
2 ) installoption=2
output "You have selected wings ${WINGS} installation only."
;;
3 ) installoption=3
output "You have selected ${PANEL} panel and wings ${WINGS} installation."
;;
4 ) installoption=4
output "You have selected to upgrade the panel to ${PANEL}."
;;
5 ) installoption=5
output "You have selected to upgrade the daemon to ${DAEMON}."
;;
6 ) installoption=6
output "You have selected to upgrade panel to ${PANEL} and daemon to ${DAEMON}."
;;
7 ) installoption=8
output "You have selected MariaDB root password reset."
;;
8 ) installoption=9
output "You have selected Database Host information reset."
;;
* ) output "You did not enter a valid selection."
install_options
esac
}
required_infos() {
output "Please enter the desired user email address:"
read -r email
output "Please enter your FQDN (panel.domain.tld):"
read -r FQDN
timezone=$(timedatectl | grep "Time zone" | awk '{ print $3 }')
dnf upgrade -y
dnf install -y bind-utils
output "Resolving DNS..."
SERVER_IP=$(dig +short myip.opendns.com @resolver1.opendns.com -4)
DOMAIN_RECORD=$(dig +short ${FQDN})
if [ "${SERVER_IP}" != "${DOMAIN_RECORD}" ]; then
output ""
output "The entered domain does not resolve to the primary public IP of this server."
output "Please make an A record pointing to your server's IP. For example, if you make an A record called 'panel' pointing to your server's IP, your FQDN is panel.domain.tld"
output "If you are using Cloudflare, please disable the orange cloud."
output "If you do not have a domain, you can get a free one at https://freenom.com"
dns_check
else
output "Domain resolved correctly. Good to go..."
fi
}
install_dependencies(){
output "Installing dependencies..."
if [ "$lsb_dist" = "rhel" ]; then
subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
rpm --import https://raw.githubusercontent.com/tommytran732/Pterodactyl-Script/master/epel9.asc
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
elif [ "$lsb_dist" = "centos" ]; then
dnf config-manager --set-enabled crb
dnf install -y epel-release epel-next-release
else
dnf config-manager --set-enabled crb
dnf install -y epel-release
fi
#Adding Remi's repo because RHEL 9 does not have php-sodium for php 8.1 yet. Also, it is unclear whether RHEL 9 will get php 8.2 and above modules later on or not.
rpm --import https://raw.githubusercontent.com/tommytran732/Pterodactyl-Script/master/remi9.asc
dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
dnf module install -y php:remi-8.1/common
dnf install -y php-bcmath php-gd php-mysqlnd php-pdo php-sodium
systemctl enable --now php-fpm
dnf module install -y composer:2/common
dnf module install -y redis:remi-7.2/common
systemctl enable --now redis
#Adding upstream repo because RHEL's version is extremely oudated.
curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | sudo bash
dnf install -y mariadb-server
systemctl enable --now mariadb
cat > /etc/yum.repos.d/nginx.repo <<- 'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
dnf config-manager --disable nginx-stable
dnf config-manager --enable nginx-mainline
dnf install -y nginx
systemctl enable --now nginx
dnf install -y tuned
tune-adm profile latency-performance
}
install_pterodactyl() {
output "Creating the databases and setting root password..."
password=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
adminpassword=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
rootpassword=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
Q0="DROP DATABASE IF EXISTS test;"
Q1="CREATE DATABASE IF NOT EXISTS panel;"
Q2="SET old_passwords=0;"
Q3="GRANT ALL ON panel.* TO 'pterodactyl'@'127.0.0.1' IDENTIFIED BY '$password';"
Q4="GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, CREATE VIEW, EVENT, TRIGGER, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON *.* TO 'admin'@'$SERVER_IP' IDENTIFIED BY '$adminpassword' WITH GRANT OPTION;"
Q5="SET PASSWORD FOR 'root'@'localhost' = PASSWORD('$rootpassword');"
Q6="DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');"
Q7="DELETE FROM mysql.user WHERE User='';"
Q8="DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';"
Q9="FLUSH PRIVILEGES;"
SQL="${Q0}${Q1}${Q2}${Q3}${Q4}${Q5}${Q6}${Q7}${Q8}${Q9}"
mysql -u root -e "$SQL"
output "Binding MariaDB/MySQL to 0.0.0.0"
if grep -Fqs "bind-address" /etc/my.cnf.d/server.cnf ; then
sed -i 's/#bind-address=0.0.0.0/bind-address=0.0.0.0/' /etc/my.cnf.d/server.cnf
output 'Restarting MariaDB process...'
systemctl restart mariadb
else
output 'A MariaDB configuration file could not be detected! Please contact support.'
fi
output "Downloading Pterodactyl..."
mkdir -p /var/www/pterodactyl
cd /var/www/pterodactyl || exit
if [ ${PANEL} = "latest" ]; then
curl -Lo panel.tar.gz https://github.com/pterodactyl/panel/releases/latest/download/panel.tar.gz
else
curl -Lo panel.tar.gz https://github.com/pterodactyl/panel/releases/download/${PANEL}/panel.tar.gz
fi
tar -xzvf panel.tar.gz
chmod -R 755 storage/* bootstrap/cache/
output "Installing Pterodactyl..."
cp .env.example .env
composer update --no-interaction
composer install --no-dev --optimize-autoloader --no-interaction
php artisan key:generate --force
php artisan p:environment:setup -n --author=$email --url=https://$FQDN --timezone=${timezone} --cache=redis --session=database --queue=redis --redis-host=127.0.0.1 --redis-pass= --redis-port=6379
php artisan p:environment:database --host=127.0.0.1 --port=3306 --database=panel --username=pterodactyl --password=$password
output "To use PHP's internal mail sending, select [mail]. To use a custom SMTP server, select [smtp]. TLS Encryption is recommended."
php artisan p:environment:mail
php artisan migrate --seed --force
php artisan p:user:make --email=$email --admin=1
sed -i 's/PTERODACTYL_TELEMETRY_ENABLED=true/PTERODACTYL_TELEMETRY_ENABLED=false/' /var/www/pterodactyl/.env
chown -R nginx:nginx * /var/www/pterodactyl
cat > /etc/systemd/system/pteros.service <<- 'EOF'
# Pterodactyl Schedule Service
# ----------------------------------
[Unit]
Description=Pterodactyl Schedule Service
[Service]
# On some systems the user and group might be different.
# Some systems use `apache` or `nginx` as the user and group.
User=nginx
Group=nginx
ExecStart=php /var/www/pterodactyl/artisan schedule:run
StandardOutput=null
Type=oneshot
EOF
cat > /etc/systemd/system/pteros.timer <<- 'EOF'
# Pterodactyl Schedule Service Timer
# ----------------------------------
[Unit]
Description=Pterodactyl Schedule Service Timer
[Timer]
OnCalendar=*-*-* *:*:00
[Install]
WantedBy=timers.target
EOF
cat > /etc/systemd/system/pteroq.service <<- 'EOF'
# Pterodactyl Queue Worker File
# ----------------------------------
[Unit]
Description=Pterodactyl Queue Worker
After=redis-server.service
[Service]
# On some systems the user and group might be different.
# Some systems use `apache` or `nginx` as the user and group.
User=nginx
Group=nginx
Restart=always
ExecStart=/usr/bin/php /var/www/pterodactyl/artisan queue:work --queue=high,standard,low --sleep=3 --tries=3
StartLimitInterval=180
StartLimitBurst=30
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
systemctl enable --now pteros.timer
systemctl enable --now pteroq.service
}
upgrade_pterodactyl(){
cd /var/www/pterodactyl && php artisan p:upgrade
chown -R nginx:nginx /var/www/pterodactyl
output "Your panel has successfully been updated to version ${PANEL}"
}
webserver_config(){
output "Configuring PHP socket..."
bash -c 'cat > /etc/php-fpm.d/www-pterodactyl.conf' <<-'EOF'
[pterodactyl]
user = nginx
group = nginx
listen = /run/php-fpm/pterodactyl.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0750
pm = ondemand
pm.max_children = 9
pm.process_idle_timeout = 10s
pm.max_requests = 200
EOF
chgrp -R nginx /var/lib/php/{opcache,session,wsdlcache}
systemctl restart php-fpm
output "Configuring Nginx web server..."
rm -f /etc/nginx/conf.d/default.conf
cat > /etc/nginx/conf.d/pterodactyl.conf <<- 'EOF'
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name FQDN;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name FQDN;
root /var/www/pterodactyl/public;
index index.php;
access_log /var/log/nginx/pterodactyl.app-access.log;
error_log /var/log/nginx/pterodactyl.app-error.log error;
# allow larger file uploads and longer script runtimes
client_max_body_size 100m;
client_body_timeout 120s;
sendfile off;
ssl_certificate /etc/letsencrypt/live/FQDN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/FQDN/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256";
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'none'; connect-src *; font-src 'self' https://fonts.gstatic.com https://cdnjs.cloudflare.com; img-src 'self' https://www.gravatar.com; frame-src https://recaptcha.net; manifest-src 'self'; script-src 'self' 'unsafe-inline' https://recaptcha.net https://www.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdnjs.cloudflare.com; frame-ancestors 'self'; block-all-mixed-content; base-uri 'none'";
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), magnetometer=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), usb=(), sync-xhr=(), xr-spatial-tracking=()";
add_header Referrer-Policy "same-origin" always;
add_header X-Content-Type-Options "nosniff" always;
#add_header X-UA-Compatible "IE=Edge" always;
add_header X-XSS-Protection "0" always;
add_header Cross-Origin-Resource-Policy same-origin;
add_header Cross-Origin-Opener-Policy same-origin;
add_header X-XSS-Protection "0" always;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php-fpm/pterodactyl.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param PHP_VALUE "upload_max_filesize = 100M \n post_max_size=100M";
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_PROXY "";
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
include /etc/nginx/fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
EOF
sed -i "s/FQDN/${FQDN}/g" /etc/nginx/conf.d/pterodactyl.conf
service nginx restart
restorecon -R /var/www/pterodactyl
setsebool -P httpd_can_network_connect 1
setsebool -P httpd_execmem 1
setsebool -P httpd_unified 1
}
install_wings() {
output "Installing Docker"
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf -y --allowerasing install docker-ce
systemctl enable --now docker
output "Installing the Pterodactyl wings..."
mkdir -p /etc/pterodactyl
cd /etc/pterodactyl || exit
if [ ${WINGS} = "latest" ]; then
curl -L -o /usr/local/bin/wings https://github.com/pterodactyl/wings/releases/latest/download/wings_linux_amd64
else
curl -L -o /usr/local/bin/wings https://github.com/pterodactyl/wings/releases/download/${WINGS}/wings_linux_amd64
fi
chmod u+x /usr/local/bin/wings
bash -c 'cat > /etc/systemd/system/wings.service' <<-'EOF'
[Unit]
Description=Pterodactyl Wings Daemon
After=docker.service
Requires=docker.service
PartOf=docker.service
[Service]
User=root
WorkingDirectory=/etc/pterodactyl
LimitNOFILE=4096
PIDFile=/var/run/wings/daemon.pid
ExecStart=/usr/local/bin/wings
Restart=on-failure
StartLimitInterval=180
StartLimitBurst=30
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
systemctl enable wings
output "Adding Fail2ban rules for Wings SFTP"
echo '[wings]
enabled = true
port = 2022
logpath = /var/log/pterodactyl/wings.log
maxretry = 5
findtime = 3600
bantime = -1
backend = systemd' | tee -a /etc/fail2ban/jail.local
bash -c 'cat > /etc/fail2ban/conf.d/wings.conf' <<-'EOF'
# Fail2Ban filter for wings (Pterodactyl daemon)
#
#
#
# "WARN: [Sep 8 18:51:00.414] failed to validate user credentials (invalid format) ip=<HOST>:51782 subsystem=sftp username=logout"
#
[INCLUDES]
before = common.conf
[Definition]
_daemon = wings
failregex = failed to validate user credentials \([^\)]+\) ip=<HOST>:.* subsystem=sftp username=.*$
ignoreregex =
[Init]
datepattern = \[%%b %%d %%H:%%M:%%S.%%f\]
EOF
systemctl restart fail2ban
output "Wings ${WINGS} has now been installed on your system."
output "You should go to your panel and configure the node now."
output "If you get `bash: wings: command not found` when running the auto deployment command, replace `wings` with `/usr/local/bin/wings` and it will work."
output "Do `systemctl start wings` after you are done configuring the node."
}
upgrade_wings(){
systemctl stop wings
if [ ${WINGS} = "latest" ]; then
curl -L -o /usr/local/bin/wings https://github.com/pterodactyl/wings/releases/latest/download/wings_linux_amd64
else
curl -L -o /usr/local/bin/wings https://github.com/pterodactyl/wings/releases/download/${WINGS}/wings_linux_amd64
fi
chmod u+x /usr/local/bin/wings
systemctl start wings
output "Your wings have been updated to version ${WINGS}."
}
firewall(){
if [ "$installoption" = "2" ]; then
if [ "$lsb_dist" = "rhel" ]; then
subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
rpm --import https://raw.githubusercontent.com/tommytran732/Pterodactyl-Script/master/epel9.asc
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
elif [ "$lsb_dist" = "centos" ]; then
dnf config-manager --set-enabled crb
dnf install -y epel-release epel-next-release
else
dnf config-manager --set-enabled crb
dnf install -y epel-release
fi
fi
output "Setting up Fail2Ban..."
dnf -y install fail2ban
systemctl enable --now fail2ban
bash -c 'cat > /etc/fail2ban/jail.local' <<-'EOF'
[DEFAULT]
# Ban hosts for ten hours:
bantime = 36000
[sshd]
enabled = true
EOF
systemctl restart fail2ban
output "Configuring your firewall..."
dnf -y install firewalld
systemctl enable --now firewalld
firewall-cmd --permanent --remove-service=cockpit
if [ "$installoption" = "1" ]; then
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=mysql
elif [ "$installoption" = "2" ]; then
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-port=2022/tcp
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --zone=trusted --add-masquerade --permanent
elif [ "$installoption" = "3" ]; then
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --permanent --add-port=2022/tcp
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --add-service=mysql
firewall-cmd --zone=trusted --add-masquerade --permanent
fi
firewall-cmd --reload
}
ssl_certs(){
output "Installing Let's Encrypt and creating an SSL certificate..."
dnf -y install certbot
if [ "$installoption" = "1" ] || [ "$installoption" = "3" ]; then
dnf -y install python3-certbot-nginx
certbot --nginx --redirect --no-eff-email --email "$email" --agree-tos -d "$FQDN"
setfacl -Rdm u:mysql:rx /etc/letsencrypt
setfacl -Rm u:mysql:rx /etc/letsencrypt
sed -i '/\[mysqld\]/a ssl-key=/etc/letsencrypt/live/'"${FQDN}"'/privkey.pem' /etc/my.cnf.d/server.cnf
sed -i '/\[mysqld\]/a ssl-ca=/etc/letsencrypt/live/'"${FQDN}"'/chain.pem' /etc/my.cnf.d/server.cnf
sed -i '/\[mysqld\]/a ssl-cert=/etc/letsencrypt/live/'"${FQDN}"'/cert.pem' /etc/my.cnf.d/server.cnf
systemctl restart mariadb
fi
if [ "$installoption" = "2" ]; then
certbot certonly --standalone --no-eff-email --email "$email" --agree-tos -d "$FQDN" --non-interactive
fi
systemctl enable --now certbot-renew.timer
}
linux_hardening(){
dnf install -y unbound
echo 'server:
chroot: ""
auto-trust-anchor-file: "/var/lib/unbound/root.key"
trust-anchor-signaling: yes
root-key-sentinel: yes
tls-ciphers: "PROFILE=SYSTEM"
hide-http-user-agent: yes
hide-identity: yes
hide-trustanchor: yes
hide-version: yes
deny-any: yes
do-not-query-localhost: yes
harden-algo-downgrade: yes
harden-large-queries: yes
harden-referral-path: yes
ignore-cd-flag: yes
max-udp-size: 3072
module-config: "validator iterator"
qname-minimisation-strict: yes
unwanted-reply-threshold: 10000000
use-caps-for-id: yes
outgoing-port-permit: 1024-65535
prefetch: yes
prefetch-key: yes
forward-zone:
name: "."
forward-tls-upstream: yes
forward-addr: 8.8.8.8#dns.google
forward-addr: 8.8.4.4#dns.google
forward-addr: 2001:4860:4860::8888#dns.google
forward-addr: 2001:4860:4860::8844#dns.google' | sudo tee /etc/unbound/unbound.conf
mkdir -p /etc/systemd/system/unbound.service.d
echo $'[Service]
MemoryDenyWriteExecute=true
PrivateDevices=true
PrivateTmp=true
ProtectHome=true
ProtectClock=true
ProtectControlGroups=true
ProtectKernelLogs=true
ProtectKernelModules=true
# This breaks using socket options like \'so-rcvbuf\'. Explicitly disable for visibility.
ProtectKernelTunables=true
ProtectProc=invisible
RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX
RestrictRealtime=true
SystemCallArchitectures=native
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete @resources
RestrictNamespaces=yes
LockPersonality=yes' | sudo tee /etc/systemd/system/unbound.service.d/override.conf
systemctl enable --now unbound
mkdir -p /etc/systemd/system/sshd.service.d
curl https://raw.githubusercontent.com/GrapheneOS/infrastructure/main/systemd/system/sshd.service.d/limits.conf -o /etc/systemd/system/sshd.service.d/limits.conf
systemctl restart sshd
curl https://raw.githubusercontent.com/GrapheneOS/infrastructure/main/chrony.conf -o /etc/chrony.conf
systemctl restart chronyd
curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/etc/modprobe.d/30_security-misc.conf -o /etc/modprobe.d/30_security-misc.conf
curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/usr/lib/sysctl.d/990-security-misc.conf -o /etc/sysctl.d/990-security-misc.conf
sed -i 's/kernel.yama.ptrace_scope=2/kernel.yama.ptrace_scope=3/g' /etc/sysctl.d/990-security-misc.conf
sudo sed -i 's/net.ipv4.icmp_echo_ignore_all=1/net.ipv4.icmp_echo_ignore_all=0/g' /etc/sysctl.d/990-security-misc.conf
sudo sed -i 's/net.ipv6.icmp.echo_ignore_all=1/net.ipv6.icmp.echo_ignore_all=0/g' /etc/sysctl.d/990-security-misc.conf
curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/usr/lib/sysctl.d/30_silent-kernel-printk.conf -o /etc/sysctl.d/30_silent-kernel-printk.conf
curl https://raw.githubusercontent.com/Kicksecure/security-misc/master/usr/lib/sysctl.d/30_security-misc_kexec-disable.conf -o /etc/sysctl.d/30_security-misc_kexec-disable.conf
sysctl -p
mkdir -p /etc/systemd/system/NetworkManager.service.d
curl https://gitlab.com/divested/brace/-/raw/master/brace/usr/lib/systemd/system/NetworkManager.service.d/99-brace.conf -o /etc/systemd/system/NetworkManager.service.d/99-brace.conf
systemctl restart NetworkManager
mkdir -p /etc/systemd/system/irqbalance.service.d
curl https://gitlab.com/divested/brace/-/raw/master/brace/usr/lib/systemd/system/irqbalance.service.d/99-brace.conf -o /etc/systemd/system/irqbalance.service.d/99-brace.conf
systemctl restart irqbalance
if [ "$lsb_dist" = "rhel" ]; then
insights-client --register
dnf install -y yara
insights-client --collector malware-detection
sed -i 's/test_scan: true/test_scan: false/' /etc/insights-client/malware-detection-config.yml
fi
}
database_host_reset(){
adminpassword=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
Q0="SET old_passwords=0;"
Q1="SET PASSWORD FOR 'admin'@'$SERVER_IP' = PASSWORD('$adminpassword');"
Q2="FLUSH PRIVILEGES;"
SQL="${Q0}${Q1}${Q2}"
mysql mysql -e "$SQL"
output "New database admin user information:"
output "User: admin"
output "Password: $adminpassword"
}
print_info(){
if [ "$installoption" = "1" ] || [ "$installoption" = "3" ]; then
print_info_database
fi
output "------------------------------------------------------------------"
output "FIREWALL INFORMATION"
output ""
output "All unnecessary ports are blocked by default."
output "Use 'firewall-cmd --permanent --add-port=<port>/tcp' to enable your desired ports."
output "------------------------------------------------------------------"
output ""
}
print_info_database(){
output "------------------------------------------------------------------"
output "MARIADB/MySQL INFORMATION"
output ""
output "Your MariaDB/MySQL root password is $rootpassword"
output ""
output "Create your MariaDB/MySQL host with the following information:"
output "Host: ${FQDN}"
output "Port: 3306"
output "User: admin"
output "Password: $adminpassword"
output "------------------------------------------------------------------"
output ""
}
#Execution
preflight
install_options
case $installoption in
1) required_infos
linux_hardening
install_dependencies
install_pterodactyl
firewall
ssl_certs
webserver_config
print_info
print_info_database
;;
2) required_infos
linux_hardening
firewall
ssl_certs
install_wings
print_info
print_info_database
;;
3) required_infos
linux_hardening
install_dependencies
install_pterodactyl
firewall
ssl_certs
webserver_config
install_wings
print_info
;;
4) upgrade_pterodactyl
;;
5) upgrade_wings
;;
6) upgrade_pterodactyl
upgrade_wings
;;
7) curl -sSL https://raw.githubusercontent.com/tommytran732/MariaDB-Root-Password-Reset/master/mariadb-104.sh | sudo bash
;;
8) database_host_reset
;;
esac