---
title: Server Deploing Sheet
tags: deploy
description:
---
#### *VPS*
<!-- Put the link to this slide here so people can follow -->
---
##
### Initial managment
```typescript=
apt update & apt upgrade
useradd -m user & usermod -aG sudo user
passwd user
mkdir config && cd config
mkdir iptables vpn uwsgi nginx fail2ban manuals docker wireguard
user=[username]
```
### SSH
#### Configure
```bash=
cd ~/config/ssh/
ln -s /home/$user/config/ssh/sshd_config /etc/ssh/sshd_config.d/ssh_config
ssh-keygen -A
```
#### SSHD config (sed '/^ *#/d; /^ *$/d' clean_conf)
```bash=
Port [port]
AddressFamily inet
ListenAddress [ip]
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
RekeyLimit 1G
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 1m
PermitRootLogin no
StrictModes yes
AllowUsers $user
MaxAuthTries 5
MaxSessions 4
PubkeyAuthentication yes
AuthorizedKeysFile /home/$user/.ssh/authorized_keys /home/$user/.ssh/authorized_keys2
IgnoreRhosts yes
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
X11Forwarding no
PrintMotd no
PrintLastLog yes
Compression no
ClientAliveInterval 60
ClientAliveCountMax 3
TCPKeepAlive no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
DenyGroups no-ssh
```
```bash=
# check config
/usr/sbin/sshd -t
sudo systemctl restart sshd
sudo systemctl status sshd
```
#### Edit ssh welcome message
```bash=
sudo apt install update-motd
echo "" > /snap/core18/2066/motd
```
### Iptables
#### Iptables params explanation
```bash=
# The order of passing the tables
https://ittricks.ru/administrirovanie/linux/531/iptables-poryadok-proxozhdeniya-tablic-i-cepochek
```
####
```bash=
# create main iptables conf file
cd configs/iptables/
nano ~/config/iptables/iptables_rules.ipv4
sudo apt-get install iptables-persistent
```
#### Disable TOR nodes and IPtables config
```bash=
# https://bozza.ru/art-297.html
# https://losst.ru/upravlenie-sluzhbami-linux
# https://losst.ru/kak-dobavit-skript-v-avtozagruzku-ubuntu
```
apt update & apt -y install ipset
```bash=
systemctl edit --force --full tornodescollector
```
```bash=
[Unit]
After=iptables.service
After=ip6tables.service
Description=TOR nodes collector
After=multi-user.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/root/tornodescollector.sh
[Install]
WantedBy=basic.target
#systemctl edit --force tornodescollector
```
```bash=
nano /root/tornodescollector.sh
```
```bash=
#!/bin/bash
# Block Tor Exit nodes
EXTERNAL_IP="IP"
# EXTERNAL_IP=$(curl ident.me) - DANGEROUS!
ipset -N TORSET iphash 2> /dev/null
# curl "https://check.torproject.org/torbulkexitlist?ip=${EXTERNAL_IP}" | xargs -n 1 ipset -A TORSET
/usr/bin/curl -sSL "https://check.torproject.org/torbulkexitlist?ip=${EXTERNAL_IP}" 2> /dev/null | xargs -n 1 ipset -A TORSET 2> /dev/null
systemctl restart iptables
```
```bash=
sudo systemctl daemon-reload
```
```bash=
sudo systemctl enable tornodescollector
```
#### /etc/iptables/rules.v4 for IPv4
```bash=
# Generated by iptables-save v1.6.0 on Sat Jun 1 11:06:45 2019
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE
COMMIT
# Completed on Sat Jun 1 11:06:45 2019
# Generated by iptables-save v1.6.0 on Sat Jun 1 11:06:45 2019
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
# Completed on Sat Jun 1 11:06:45 2019
# Generated by iptables-save v1.6.0 on Sat Jun 1 11:06:45 2019
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:SRV-Firewall-1-INPUT - [0:0]:TOR - [0:0]
-A INPUT -j TOR
-A TOR -m set --match-set TORSET src -j DROP
-A INPUT -j VPN-Firewall-1-INPUT
-A FORWARD -j VPN-Firewall-1-INPUT
-A VPN-Firewall-1-INPUT -s 127.0.0.1/32 -p icmp -m icmp --icmp-type any -j ACCEPT
-A VPN-Firewall-1-INPUT -s 109.252.0.0/16 -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A VPN-Firewall-1-INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A VPN-Firewall-1-INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A VPN-Firewall-1-INPUT -p tcp -m tcp --dport 44300 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 109.252.0.0/16 -p udp -m udp --dport 51820 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 176.59.0.0/16 -p udp -m udp --dport 51820 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 212.3.128.0/19 -p udp -m udp --dport 51820 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 94.25.0.0/16 -p udp -m udp --dport 51820 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 109.252.0.0/16 -p tcp -m tcp --dport 44327 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 176.59.0.0/16 -p tcp -m tcp --dport 44327 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 212.3.128.0/19 -p tcp -m tcp --dport 44327 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 94.26.0.0/16 -p tcp -m tcp --dport 44327 -j ACCEPT
-A VPN-Firewall-1-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A VPN-Firewall-1-INPUT -s 109.252.0.0/16 -p tcp -m state --state NEW -m tcp --dport 43900 -j ACCEPT
-A VPN-Firewall-1-INPUT -s 109.252.0.0/16 -p udp -m state --state NEW -m udp --dport 44000 -j ACCEPT
-A VPN-Firewall-1-INPUT -i tun+ -j ACCEPT
-A VPN-Firewall-1-INPUT -i lo -j ACCEPT
-A VPN-Firewall-1-INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m multiport --dports 80,443,44327 -m connlimit --connlimit-above 10 --connlimit-mask 9 --connlimit-sad>
-A VPN-Firewall-1-INPUT -p icmp -m icmp --icmp-type 8 -j DROP
-A VPN-Firewall-1-INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
-A VPN-Firewall-1-INPUT -i eth0 -p tcp -j DROP
-A VPN-Firewall-1-INPUT -i eth0 -p udp -j DROP
# Completed on Sat Jun 1 11:06:45 2019
```
#### /etc/iptables/rules.v6 for IPv6.
```bash=
# Generated by ip6tables-save v1.8.7 on Sun Jun 6 01:25:37 2021
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p ipv6-icmp -j DROP
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -j DROP
-A INPUT -p udp -j DROP
COMMIT
# Completed on Sun Jun 6 01:25:37 2021
#ip6tables rules
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables -I INPUT 1 -i lo -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -A INPUT -p tcp --dport http -j ACCEPT
ip6tables -A INPUT -p tcp --dport https -j ACCEPT
ip6tables-save > /etc/ip6tables.conf
# manual mode
iptables-resotre < /etc/iptables/rules.v4
```
#### Disable ipv6
```bash
sudo nano /etc/sysctl.conf
#add at the end of the config file
net.ipv6.conf.all.disable_ipv6 = 1
sudo sysctl -p
sudo systemctl restart iptables
```
```bash=
/etc/iptables/rules.v4
# all other version are depricated
#nano ~/config/iptables/iptables_restore.ipv4
## -->
###!/bin/sh
##/sbin/iptables-restore < /home/$user/config/iptables/iptables_rules.ipv4
## --
#sudo ln -s sudo ln -s /home/$user/config/iptables/iptables_restore.ipv4 /etc/network/if-pre-up.d/iptables_restore
```
### Wireguard install
```bash=
sudo add-apt-repository ppa:wireguard/wireguard
sudo apt install wireguard
```
### Rkhunter install
```bash=
# https://habr.com/ru/company/first/blog/242865/
# by root
sudo apt -y install rkhunter mailutils
# optional (errors)
nano /etc/rkhunter.conf
MIRRORS_MODE=1 ---> MIRRORS_MODE=0
UPDATE_MIRRORS=0 ---> UPDATE_MIRRORS=1
WEB_CMD="/bin/false" ---> WEB_CMD=""
MAIL_CMD=echo "Rkhunter warnings were received" | mail -s "rkhunter status message" mail -aFrom:mail
# Add mail for alerts
nano /etc/rkhunter.conf
MAIL-ON-WARNING="mail.com"
# manual launch
rkhunter -c --enable all --disable none --rwo
# collect hashes of sys files
rkhunter --propupd
# add to crontab job
sudo nano /etc/cron.daily/rkhunters
#!/bin/sh
(
/usr/bin/rkhunter --versioncheck
/usr/bin/rkhunter --update
/usr/bin/rkhunter -c --sk --rwo) | mail -s "rkhunter scan status from $(date)" $mail -aFrom:$mail
chmod +x /etc/cron.daily/rkhunters
# or
@daily /usr/bin/rkhunter --cronjob --update --quiet
# parse rkhunter log file
sudo cat /var/log/rkhunter.log | grep -A5 "\[ Warning \]"
# for false-positive
# SCRIPTWHITELIST="/sbin/ifup /sbin/ifdown /usr/bin/groups /usr/bin/ldd /usr/bin/whatis"
# for hidden files and folders
# ALLOWHIDDENDIR="/etc/.java"
# ALLOWHIDDENFILE="/etc/.java"
# add mail newsletter
## https://www.dmosk.ru/miniinstruktions.php?mini=postfix-over-yandex
sudo nano /etc/postfix/main.cf
---
relayhost =
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/private/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_type = cyrus
smtp_sasl_mechanism_filter = login
smtp_sender_dependent_authentication = yes
sender_dependent_relayhost_maps = hash:/etc/postfix/private/sender_relay
smtp_tls_CAfile = /etc/postfix/ca.pem
smtp_use_tls = yes
---
# create private config files
mkdir /etc/postfix/private
sudo nano /etc/postfix/private/sender_relay
---
@[domain] smtp.yandex.ru
---
sudo nano /etc/postfix/private/sasl_passwd
---
[smtp.yandex.ru]:587 $mailName@$domain:$pass
---
postmap /etc/postfix/private/{sasl_passwd,sender_relay}
# get certificate of the smtp server
openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:587
#to file
/etc/postfix/ca.pem
# restart postfix service
sudo systemctl restart postfix
# test mail server
echo "Test text" | mail -s "Test title" $toWhomEmail -aFrom:$FromWhoEmail
# set default hashes
sudo rkhunter --propupd
```
#### Replace OpenSSH header
```bash=
sshd -V
cp /usr/sbin/sshd /tmp & cd /tmp
strings -t d -a -n 7 sshd | grep OpenSSH
dd if=./sshd bs=1 skip= [address] count=[count] | od -A n -c
dd if=./sshd bs=1 count=[address] of=sshd.1
dd if=./sshd bs=1 skip=[address] count=[count] of=sshd.2
dd if=./sshd bs=1 skip=[address] count=999999999 of=sshd.3
od -A n -c sshd.2
sed -i 's/SEARCH_REGEX/REPLACEMENT/g' sshd.2
#nano sshd.2
#tr -d '\n' < title > sshd.2
cat sshd.* > sshd.new
strings -t d -a -n 7 sshd.new | grep OpenSSH
chmod 755 ./sshd.new
cp /usr/sbin/sshd /usr/sbin/sshd.bak
rm /usr/sbin/sshd
cp /tmp/sshd.new /usr/sbin/sshd
# Example
sshd -V
strings -t d -a -n 7 sshd | grep OpenSSH
dd if=./sshd bs=1 skip=526539 count=29 | od -A n -c
dd if=./sshd bs=1 count=526539 of=sshd.1
dd if=./sshd bs=1 skip=526539 count=30 of=sshd.2
dd if=./sshd bs=1 skip=526569 count=999999999 of=sshd.3
#SGCMS Fingerprint: X64_vsd12d
#SGCMS FGPT:X64_St24aDr49zRms2
# check the title
dd if=./sshd.2 bs=1 skip=0 count=999999999 | d -A n -c
sed -i 's/OpenSSH_8.4p1 Ubuntu-5ubuntu1/SGCMS FGPT:X64_St24aDr49zRms2/g' sshd.2
cat sshd.* > sshd.new
chmod 755 ./sshd.new
strings -t d -a -n 7 sshd.new | grep OpenSSH
chmod +x sshd.new
cp /tmp/sshd.new /user/sbin/sshd
# explanation (with errors! wrong indents!)
# https://poweruser.guru/questions/782382/%D1%81%D0%BA%D1%80%D1%8B%D1%82%D1%8C-%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D1%8E-ssh
```
### Fail2ban
#### Manual
```
#https://www.dmosk.ru/instruktions.php?object=fail2ban
```
#### Configure application
```bash=
sudo apt install fail2ban
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
# /etc/fail2ban/fail2ban.conf
# /etc/fail2ban/jail.conf - jail config
# port configs
# SSH
#sudo nano /etc/fail2ban/jail.d/ssh.conf
cd ~/config/fail2ban
nano ssh.conf
# ---
[ssh]
enabled = true
port = ssh
filter = sshd
action = iptables[name=sshd]
logpath = /var/log/auth.log
# NGINX
# sudo nano /etc/fail2ban/jail.d/nginx.conf
# ---
[nginx]
enabled = true
port = http,https
filter = nginx-http-auth
action = iptables-multiport[name=nginx, port="http,https", protocol=tcp]
logpath = /var/log/nginx/error.log
#create symlinks to configs
sudo ln -s /home/$user/config/fail2ban/ssh.conf /etc/fail2ban/jail.d/ssh.conf
sudo ln -s /home/$user/config/fail2ban/nginx.conf /etc/fail2ban/jail.d/nginx.conf
sudo systemctl restart fail2ban.service
```
#### fail2ban commands
```bash=
# Check rules and configs are being used
fail2ban-client status
# Check details and ban statistic of the current rules
fail2ban-client status ssh
# Check /var/log/auth.log for IP
sudo cat auth.log | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"
# Check /var/log/auth.log for IPv6
sudo cat auth.log | grep -E -o "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"
```
### DJANGO
```bash=
sudo apt update
sudo apt install python3-pip
sudo -H pip3 install --upgrade pip
sudo pip3 install virtualenv virtualenvwrapper
#echo "export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3" >> ~/.bashrc
echo "export WORKON_HOME=home/$user/config/environment" >> ~/.bashrc
echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrc
export PYTHONPATH='/home/$user/config/django/lib/python3.4'
source ~/.bashrc
cd ~/config/django/
mkvirtualenv [project_name]
pip3 install django
# test django server
sudo `which python3` manage.py runserver 0.0.0.0:8080
#deactivate env
deactivate
#activate env
source bin/activate
```
#### UWSGI (I)
```bash=
sudo apt-get install python3-dev
sudo -H pip3 install uwsgi
# test UWSGI
#sudo uwsgi --http :8080 --home /home/$(whoami)/config/environment/$(whoami) --chdir /home/$(whoami)/config/djanago/$project/ -w $project.wsgi
cd ~/config/uwsgi
sudo mkdir -p /etc/uwsgi/sites
sudo ln -s /home/$(whoami)/config/uwsgi/$project.ini /etc/uwsgi/sites/
```
#### UWSGI project config file
```bash=
[uwsgi]
uid = $user
project = $project
base = /home/%(uid)/config/django
chdir = %(base)/%(project)
module = %(project).wsgi:application
master = true
callable = $project
pidfile = /run/uwsgi/%(project).pid
env = LANG=en_US.UTF-8
env = DJANGO_SETTINGS_MODULE=$project.settings
pythonpath = %(base)/%(project)
plugins = python3
virtualenv = /home/$user/config/environment/$project
socket = /run/uwsgi/%(project).socket
chmod-socket = 660
chown-socket = %(uid):www-data
processes = 5
enable-threads = true
vacuum = true
no-orphans = true
autoload = true
#touch-reload = %(base)/%(porject)/touch.reload
harakiri = 30
buffer-size = 32768
```
```bash=
# uwsgi service config creating
sudo ln -s /home/$(whoami)/config/uwsgi/uwsgi.service /etc/systemd/system/uwsgi.service
```
#### UWSGI service config file
```bash=
[Unit]
Description=uWSGI Emperor service
[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown $user:www-data /run/uwsgi'
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all
[Install]
WantedBy=multi-user.targe
```
### NGINX
#### Configure server
```bash=
server=[server_url]
sudo apt-get install nginx -y
sudo nano /etc/nginx/nginx.conf
cd ~/config/nginx
sudo ln -s /home/$(whoami)/config/nginx/nginx.conf /etc/nginx/sites-available/$(echo $project)
sudo ln -s /etc/nginx/sites-available/$(echo $project) /etc/nginx/sites-enabled
sudo usermod -a -G www-data $(whoami)
sudo mkdir -p /var/www/$project/static
sudo chown -R $(whoami):www-data /var/www/$project
sudo chmod -R 755 /var/www/$project
```
#### NGINX server config
```bash=
server {
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 10M;
large_client_header_buffers 2 1k;
keepalive_timeout 5 5;
send_timeout 10;
if ($host !~ ^($server)$ ) {
return 444;
}
if ( $http_referer ~* (babes|forsale|girl|jewerly|love|nude|nudit|organic|poker|porn|sex|teen|oral|anal) )
{
return 403;
}
location /media {
valid_referers none blocked $server;
if ($invalid_referer) {return 444;}
alias /var/www/$project/media;
}
location /static {
alias /var/www/$project/static;
}
location / {
uwsgi_pass unix:///run/uwsgi/$server.socket;
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/$server.io/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/$server.io/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = $server) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name $server;
return 404; # managed by Certbot
}
sudo nginx -t
sudo systemctl enable nginx
sudo systemctl enable uwsgi
```
#### Let`s Encrypt certificate gaining
```bash=
sudo snap install certbot --classic
#sudo apt install python-certbot-nginx
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot run --nginx
# enable auto renewal
sudo certbot renew --dry-run
# root
cd /etc/nginx/
nano acme
# ---
location /.well-known {
root /var/www/crypt;
}
mkdir&cd /var/www/crypt/.well-known
nano example.html
curl -L http://$server/.well-known/example.html
cat /etc/letsencrypt/live/*/cert.pem | openssl x509 -text | grep -o 'DNS:[^,]*' | cut -f2 -d:
```
TLS cetificates
```bash=
openssl req -x509 -out localhost.crt -keyout localhost.key \
-newkey rsa:2048 -nodes -sha256 \
-subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth"
```