├── .gitignore ├── docker-compose.yml ├── fail2ban ├── action.d │ └── npm-firewall-block.conf ├── filter.d │ └── npm-docker.conf └── jail.d │ └── jail.local ├── firewall.sh ├── license ├── readme.md ├── setup.sh └── systemd ├── reloadFail2ban.service └── reloadFail2ban.timer /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | tmp 3 | .idea -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | networks: 2 | CHANGE_TO_USERNAME: 3 | external: true 4 | database: 5 | external: true 6 | 7 | volumes: 8 | mariadb: 9 | 10 | services: 11 | portainer: 12 | image: portainer/portainer-ce:latest 13 | container_name: portainer 14 | restart: unless-stopped 15 | networks: 16 | - CHANGE_TO_USERNAME 17 | volumes: 18 | - /etc/localtime:/etc/localtime:ro 19 | - ./portainer:/data 20 | - /var/run/docker.sock:/var/run/docker.sock:ro 21 | ports: 22 | - 127.0.0.1:6900:9000 23 | 24 | mariadb: 25 | image: linuxserver/mariadb 26 | container_name: mariadb 27 | restart: unless-stopped 28 | networks: 29 | - CHANGE_TO_USERNAME 30 | - database 31 | volumes: 32 | - mariadb:/config 33 | environment: 34 | PUID: USER_UID 35 | PGID: USER_GID 36 | MYSQL_ROOT_PASSWORD: 'MARIA_DB_ROOT_PASSWORD' 37 | TZ: USER_TIMEZONE 38 | # nginx proxy database 39 | MYSQL_USER: 'npm' 40 | MYSQL_PASSWORD: 'NPM_DB_PASSWORD' 41 | MYSQL_DATABASE: npm 42 | 43 | phpmyadmin: 44 | image: linuxserver/phpmyadmin 45 | container_name: phpmyadmin 46 | networks: 47 | - database 48 | environment: 49 | PUID: USER_UID 50 | PGID: USER_GID 51 | PMA_HOST: mariadb 52 | PMA_USER: root 53 | PMA_PASSWORD: 'MARIA_DB_ROOT_PASSWORD' 54 | TZ: USER_TIMEZONE 55 | ports: 56 | - 127.0.0.1:6902:80 57 | restart: unless-stopped 58 | 59 | nginx-proxy-manager: 60 | image: 'jc21/nginx-proxy-manager:latest' 61 | container_name: nginx-proxy-manager 62 | restart: unless-stopped 63 | networks: 64 | - CHANGE_TO_USERNAME 65 | ports: 66 | - '80:80' # Public HTTP Port 67 | - '443:443' # Public HTTPS Port 68 | - '127.0.0.1:6901:81' # Admin Web Port 69 | environment: 70 | DB_MYSQL_HOST: 'mariadb' 71 | DB_MYSQL_PORT: 3306 72 | DB_MYSQL_USER: 'npm' 73 | DB_MYSQL_PASSWORD: 'NPM_DB_PASSWORD' 74 | DB_MYSQL_NAME: 'npm' 75 | TZ: USER_TIMEZONE 76 | volumes: 77 | - ./npm/data:/data 78 | # - ./npm/nginx:/etc/nginx 79 | - ./npm/letsencrypt:/etc/letsencrypt 80 | 81 | filebrowser: 82 | image: hurlenko/filebrowser 83 | container_name: filebrowser 84 | user: 'USER_UID:USER_GID' 85 | ports: 86 | - 127.0.0.1:6903:8080 87 | volumes: 88 | - /home/CHANGE_TO_USERNAME:/data 89 | - ./filebrowser/config:/config 90 | environment: 91 | - FB_BASEURL=/ 92 | restart: unless-stopped 93 | 94 | watchtower: 95 | image: containrrr/watchtower 96 | container_name: watchtower 97 | volumes: 98 | - /var/run/docker.sock:/var/run/docker.sock 99 | restart: unless-stopped 100 | 101 | fail2ban: 102 | container_name: fail2ban 103 | hostname: fail2ban 104 | cap_add: 105 | - NET_ADMIN 106 | - NET_RAW 107 | environment: 108 | - TZ=USER_TIMEZONE 109 | - F2B_DB_PURGE_AGE=3d 110 | image: crazymax/fail2ban:latest 111 | network_mode: host 112 | restart: unless-stopped 113 | volumes: 114 | - ./fail2ban/data:/data 115 | - ./npm/data/logs:/var/log/npm 116 | -------------------------------------------------------------------------------- /fail2ban/action.d/npm-firewall-block.conf: -------------------------------------------------------------------------------- 1 | [Definition] 2 | 3 | actionban = iptables -I FORWARD -s -j DROP 4 | 5 | actionunban = iptables -D FORWARD -s -j DROP 6 | -------------------------------------------------------------------------------- /fail2ban/filter.d/npm-docker.conf: -------------------------------------------------------------------------------- 1 | [INCLUDES] 2 | 3 | [Definition] 4 | 5 | failregex = ^.+ (405|404|403|401|400|\-) (405|404|403|401|400) - .+ \[Client \] \[Length .+\] ".+" .+$ 6 | 7 | ignoreregex = ^.+ (404|\-) (404) - .+".+(\.png|\.txt|\.jpg|\.jpeg|\.webp|\.ico|\.js|\.css)[/]" \[Client \] \[Length .+\] ".+" .+$ -------------------------------------------------------------------------------- /fail2ban/jail.d/jail.local: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | # "bantime.increment" allows to use database for searching of previously banned ip's to increase a 3 | # default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32... 4 | bantime.increment = true 5 | 6 | # "bantime.rndtime" is the max number of seconds using for mixing with random time 7 | # to prevent "clever" botnets calculate exact time IP can be unbanned again: 8 | bantime.rndtime = 2048 9 | 10 | # for bantime=600 the multipliers are minutes and equal: 10 min, 30 min, 1 hour, 6 hours, 12 hour, 1 day, 2 day 11 | bantime.multipliers = 1 3 6 36 72 144 288 12 | 13 | # "bantime" is the number of seconds that a host is banned. 14 | bantime = 600 15 | 16 | # A host is banned if it has generated "maxretry" during the last "findtime" seconds. 17 | findtime = 60 18 | 19 | # "maxretry" is the number of failures before a host get banned. 20 | maxretry = 8 21 | 22 | # use forward chain 23 | chain = FORWARD 24 | 25 | [npm-docker] 26 | # IPs that trigger too many 403 or 404 27 | enabled = true 28 | ignoreip = 127.0.0.1/8 192.168.1.0/24 172.16.0.0/12 29 | action = npm-firewall-block 30 | filter = npm-docker 31 | logpath = /var/log/npm/proxy-host-*_access.log -------------------------------------------------------------------------------- /firewall.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -e 4 | 5 | # runs on first login to set up and save firewall rules 6 | 7 | SSH_PORT=REPLACE_ME 8 | 9 | read -r -p "$(echo -e "\e[32mWelcome! The last thing we need to do is set up and save firewall rules. Do you want to do this now (y/n)?\e[0m ")" yn 10 | 11 | if [[ ! $yn =~ ^[Yy]$ ]] 12 | then 13 | echo "Goodbye. This script will run again next time you log in." 14 | exit 15 | fi 16 | 17 | # allow return traffic for outgoing connections initiated by the server itself 18 | sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 19 | # allow loopback traffic from localhost 20 | sudo iptables -A INPUT -i lo -j ACCEPT 21 | sudo iptables -A INPUT ! -i lo -s 127.0.0.0/8 -j REJECT 22 | # allow http, https, ssh 23 | sudo iptables -A INPUT -p tcp -m multiport --dports 80,443,$SSH_PORT -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT 24 | # set input policy to drop everything else 25 | sudo iptables --policy INPUT DROP 26 | 27 | sudo apt install iptables-persistent -y 28 | 29 | # don't need to run this as it runs automatically on install 30 | # sudo netfilter-persistent save 31 | 32 | echo -e "\n\e[32mFirewall configured 👍. If you didn't save rules, please run sudo netfilter-persistent save :)\e[0m\n" 33 | 34 | rm ~/firewall.sh -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Henry Dollman (henrygd.me) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Simple setup script for Debian / Ubuntu servers 2 | 3 | Run as root on a fresh installation 4 | 5 | ```bash 6 | curl -s https://raw.githubusercontent.com/henrygd/docker-server-setup/main/setup.sh > setup.sh && chmod +x ./setup.sh && ./setup.sh 7 | ``` 8 | 9 | ### Hardens and configures system 10 | 11 | - Creates non-root user with sudo and docker privileges. 12 | 13 | - Updates packages and optionally enables unattended-upgrades. 14 | 15 | - Changes SSH port and disables password login through SSH. 16 | 17 | - Configures firewall to block ingress except on ports 80, 443, and your chosen SSH port. 18 | 19 | - Fail2ban working out of the box to block malicious bot traffic to public web applications. 20 | 21 | - Ensures the server is set to your preferred time zone. 22 | 23 | - Adds aliases like `dcu` / `dcd` / `dcr` for docker compose up / down / restart. 24 | 25 | ### Installs docker, docker compose, and selected services 26 | 27 | Besides Nginx Proxy Manager, all services are tunneled through SSH and not publicly accessible. The following are installed by default: 28 | 29 | - **[Portainer](https://github.com/portainer/portainer)** and **[ctop](https://github.com/bcicen/ctop)** for easy container management with GUI and terminal. 30 | 31 | - **[Nginx Proxy Manager](https://github.com/NginxProxyManager/nginx-proxy-manager)** for publicly exposing your services with automatic SSL. 32 | 33 | - **[MariaDB database](https://hub.docker.com/r/linuxserver/mariadb)** used by Nginx Proxy Manager and any other apps you want. 34 | 35 | - **[phpMyAdmin](https://hub.docker.com/r/linuxserver/phpmyadmin)** for graphical administration of the MariaDB database. 36 | 37 | - **[File Browser](https://github.com/filebrowser/filebrowser)** for graphical file management. 38 | 39 | - **[Fail2ban](https://github.com/crazy-max/docker-fail2ban)** configured to read Nginx Proxy Manager logs and block malicious IPs in iptables. 40 | 41 | - **[Watchtower](https://github.com/containrrr/watchtower)** to automatically update running containers to the latest image version. 42 | 43 | These are defined and can be disabled in `~/server/docker-compose.yml`. 44 | 45 | ## Notes 46 | 47 | Debian / Ubuntu derivatives like Raspbian should work but haven't been tested. 48 | 49 | There is a docker network with the same name as your username. If you create new containers in that that network, you can use the container name as a hostname in Nginx Proxy Manager. 50 | 51 | If you need to open a port for Wireguard or another service, [allow the port in iptables](https://www.digitalocean.com/community/tutorials/iptables-essentials-common-firewall-rules-and-commands) and run `sudo netfilter-persistent save` to save rules. 52 | 53 | Make sure you have a good backup solution in place. I recommend **[Kopia](https://github.com/kopia/kopia)**. 54 | 55 | To export the MariaDB database to disk for backup, you can use the command below (you may want to change the output directory). 56 | 57 | ```bash 58 | docker exec mariadb sh -c 'mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > ~/mariadb.sql 59 | ``` 60 | 61 | If you want to monitor uptime, check out **[Uptime Kuma](https://github.com/louislam/uptime-kuma)**, but you should run this from a different machine. 62 | 63 | ### Working with Fail2ban 64 | 65 | You can view logs for Fail2ban in Dozzle or by using the `docker logs` command. 66 | 67 | The jail is reloaded every six hours with a systemd timer to pick up log files from new proxy hosts. 68 | 69 | Additional rules may be added to the container in `~/server/fail2ban`. Use the FORWARD chain (not INPUT or DOCKER-USER) and make sure the filter regex is using the NPM log format - `[Client ]`. 70 | 71 | **View status of jail and currently banned IPs.** 72 | 73 | ```bash 74 | docker exec fail2ban sh -c "fail2ban-client status npm-docker" 75 | ``` 76 | 77 | **Unban an IP in Fail2ban jail.** Replace `0.0.0.0` with the IP you want unbanned. 78 | 79 | ```bash 80 | docker exec fail2ban sh -c "fail2ban-client set npm-docker unbanip 0.0.0.0" 81 | ``` 82 | 83 | **Whitelist an IP to avoid bans.** Edit the jail config using `nano` or `vi` - then find the line starting with `ignoreip`. [Add further IPs separated by spaces](https://fail2ban.org/wiki/index.php/Whitelist). Reload the jail for the changes to take effect immediately. 84 | 85 | ```bash 86 | sudo vi ~/server/fail2ban/data/jail.d/jail.local 87 | ``` 88 | 89 | **Manually reload the jail.** Optional if you want protection for a newly created site right away. Jail automatically reloads every six hours. 90 | 91 | ```bash 92 | docker exec fail2ban sh -c "fail2ban-client reload npm-docker" 93 | ``` 94 | 95 | ### Logs 96 | 97 | Nginx Proxy Manager logs are located in `~/server/npm/data/logs/`. You need the ID of the proxy host you want to view, which you can find by clicking the three dots in NPM. These logs are limited to web requests and are rotated weekly. 98 | 99 | Example command to view live log: `tail -f ~/server/npm/data/logs/proxy-host-1_access.log` 100 | 101 | Example command search log for IP: `grep "0.0.0.0" ~/server/npm/data/logs/proxy-host-1_access.log` 102 | 103 | ### Using with Cloudflare 104 | 105 | If you proxy traffic through Cloudflare and want to use Fail2ban, additional configuration is required to avoid banning Cloudflare IPs. Please reference the guides below. 106 | 107 | Fail2ban configuration is located in `~/server/fail2ban`. 108 | 109 | - https://www.youtube.com/watch?v=Ha8NIAOsNvo (and [companion article](https://dbt3ch.com/books/fail2ban/page/how-to-install-and-configure-Fail2ban-to-work-with-nginx-proxy-manager) by DB Tech) 110 | 111 | - https://blog.lrvt.de/fail2ban-with-nginx-proxy-manager/ 112 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # exit on error 4 | set -e 5 | 6 | # clear screen 7 | clear 8 | 9 | # variables 10 | GREEN="\e[32m" 11 | CYAN="\e[36m" 12 | YELLOW="\e[33m" 13 | ENDCOLOR="\e[0m" 14 | REPO="henrygd/docker-server-setup" 15 | CUR_TIMEZONE=$(timedatectl show | grep zone | sed 's/Timezone=//g'); 16 | MARIA_DB_ROOT_PASSWORD=$(< /dev/urandom tr -dc A-Z-a-z-0-9 | head -c"${1:-20}" | sed 's/-/_/g') 17 | NPM_DB_PASSWORD=$(< /dev/urandom tr -dc A-Z-a-z-0-9 | head -c"${1:-20}" | sed 's/-/_/g') 18 | 19 | # intro message 20 | echo -e "${GREEN}Welcome! This script should be run as the root user on a new Debian or Ubuntu server.${ENDCOLOR}\n" 21 | 22 | # change timezone (works on debian / ubuntu / fedora) 23 | read -r -p "$(echo -e "The system time zone is ${YELLOW}$CUR_TIMEZONE${ENDCOLOR}. Do you want to change it (y/n)?${ENDCOLOR} ")" yn 24 | if [[ $yn =~ ^[Yy]$ ]]; then 25 | if command -v dpkg-reconfigure &> /dev/null; then 26 | dpkg-reconfigure tzdata; 27 | else 28 | read -r -p "Enter time zone: " new_timezone; 29 | if timedatectl set-timezone "$new_timezone"; then 30 | echo -e "${GREEN}Time zone has changed to: $new_timezone ${ENDCOLOR}" 31 | else 32 | echo -e "Run ${CYAN}timedatectl list-timezones${ENDCOLOR} to view all time zones"; 33 | exit; 34 | fi 35 | fi 36 | fi 37 | 38 | # create user account (works on debian / ubuntu / fedora) 39 | read -r -p "$(echo -e "\nEnter username for the user to be created: ")" username 40 | while [[ ! $username =~ ^[a-z][-a-z0-9]*$ ]]; do 41 | read -r -p "Invalid format. Enter username for the user to be created: " username 42 | done 43 | useradd -m -s /bin/bash "$username" 44 | passwd "$username" 45 | usermod -aG sudo "$username" || usermod -aG wheel "$username" 46 | 47 | echo "" 48 | 49 | # SSH port prompt 50 | read -r -p "Which port do you want to use for SSH (not 6900-6903 please)? " ssh_port 51 | while (( ssh_port < 1000 || ssh_port > 65000)); do 52 | read -r -p "Please use a number between 1000 and 65000: " ssh_port 53 | done 54 | 55 | # add ssh key 56 | mkdir -p /home/"$username"/.ssh 57 | # check if root has authorized_keys already 58 | if [ -s /root/.ssh/authorized_keys ]; then 59 | cp /root/.ssh/authorized_keys /home/"$username"/.ssh/authorized_keys 60 | else 61 | # if no keys, ask for key instead 62 | read -r -p "Please paste your public SSH key: " sshkey 63 | echo "$sshkey" >> /home/"$username"/.ssh/authorized_keys 64 | fi 65 | # fix permissions 66 | chown -R "$username": /home/"$username"/.ssh 67 | 68 | # add / update packages 69 | echo -e "${CYAN}Updating system & packages...${ENDCOLOR}" 70 | 71 | # update system 72 | apt update && apt upgrade -y 73 | apt install git unattended-upgrades -y 74 | 75 | # install docker 76 | curl -fsSL https://get.docker.com -o /tmp/get-docker.sh 77 | sh /tmp/get-docker.sh 78 | 79 | # unattended-upgrades 80 | echo -e "${CYAN}Setting up unattended-upgrades...${ENDCOLOR}" 81 | dpkg-reconfigure --priority=low unattended-upgrades 82 | 83 | # docker stuff 84 | echo -e "${CYAN}Setting up docker containers...${ENDCOLOR}" 85 | 86 | # clone repo and copy files 87 | rm -r /tmp/docker-server ||: 88 | git clone --depth=1 "https://github.com/$REPO.git" /tmp/docker-server 89 | mkdir -p /home/"$username"/server/fail2ban 90 | cp -r /tmp/docker-server/fail2ban /home/"$username"/server/fail2ban/data 91 | cp /tmp/docker-server/docker-compose.yml /home/"$username"/server/docker-compose.yml 92 | cp /tmp/docker-server/firewall.sh /home/"$username"/firewall.sh 93 | sed -i "s/REPLACE_ME/$ssh_port/" "/home/$username/firewall.sh" 94 | 95 | # create docker networks 96 | docker network create "$username" 97 | docker network create database 98 | 99 | 100 | # replace docker compose file with user input, and start 101 | sed -i "s/CHANGE_TO_USERNAME/$username/" "/home/$username/server/docker-compose.yml" 102 | sed -i "s/MARIA_DB_ROOT_PASSWORD/$MARIA_DB_ROOT_PASSWORD/" "/home/$username/server/docker-compose.yml" 103 | sed -i "s/NPM_DB_PASSWORD/$NPM_DB_PASSWORD/" "/home/$username/server/docker-compose.yml" 104 | sed -i "s/USER_UID/$(id -u "$username")/" "/home/$username/server/docker-compose.yml" 105 | sed -i "s/USER_GID/$(id -g "$username")/" "/home/$username/server/docker-compose.yml" 106 | sed -i "s|USER_TIMEZONE|$(timedatectl show | grep zone | sed 's/Timezone=//g')|" "/home/$username/server/docker-compose.yml" 107 | docker compose -f /home/"$username"/server/docker-compose.yml up -d 108 | 109 | # dummy logs so fail2ban doesn't shut down 110 | mkdir -p /home/"$username"/server/npm/data/logs 111 | touch /home/"$username"/server/npm/data/logs/proxy-host-{1..5}_access.log 112 | 113 | # fix permissions 114 | chown "$username": /home/"$username"/server /home/"$username"/server/docker-compose.yml /home/"$username"/firewall.sh 115 | chown -R "$username": /home/"$username"/server/filebrowser 116 | 117 | # add user to docker users 118 | usermod -aG docker "$username" 119 | 120 | # systemd timer to reload fail2ban jail every six hours 121 | cp /tmp/docker-server/systemd/* /etc/systemd/system 122 | systemctl start reloadFail2ban.timer 123 | systemctl enable reloadFail2ban.timer > /dev/null 2>&1 124 | 125 | # update SSH config 126 | echo -e "\n${CYAN}Updating SSH config...${ENDCOLOR}" 127 | { 128 | echo "Port $ssh_port" 129 | echo "PermitRootLogin prohibit-password" 130 | echo "PubkeyAuthentication yes" 131 | echo "PasswordAuthentication no" 132 | echo "X11Forwarding no" 133 | } >> /etc/ssh/sshd_config 134 | 135 | echo -e "${CYAN}Restarting SSH daemon...${ENDCOLOR}\n" 136 | systemctl restart sshd 137 | 138 | # verify ssh key is correct 139 | cat /home/"$username"/.ssh/authorized_keys 140 | read -r -p "$(echo -e "\nIs the above SSH key(s) correct (y/n)? ")" ssh_correct 141 | while [[ ! $ssh_correct =~ ^[Yy]$ ]]; do 142 | read -r -p "Please paste your public SSH key: " sshkey 143 | echo "$sshkey" >> /home/"$username"/.ssh/authorized_keys 144 | cat /home/"$username"/.ssh/authorized_keys 145 | read -r -p "$(echo -e "\nIs the above SSH key(s) correct (y/n)? ")" ssh_correct 146 | done 147 | 148 | # aliases / .bashrc stuff 149 | { 150 | echo 'alias dcu="docker compose up -d"'; 151 | echo 'alias dcd="docker compose down"'; 152 | echo 'alias dcu="docker compose up -d"'; 153 | echo 'alias dcr="docker compose restart"'; 154 | echo 'alias boost="curl -s https://raw.githubusercontent.com/BOOST-Creative/docker-server-setup/main/boost.sh > ~/.boost.sh && chmod +x ~/.boost.sh && ~/.boost.sh"'; 155 | echo 'alias ctop="docker run --rm -ti --name=ctop --volume /var/run/docker.sock:/var/run/docker.sock:ro quay.io/vektorlab/ctop:latest"'; 156 | echo 'echo -e "\nPortainer: \e[34mhttp://localhost:6900\n\e[0mNginx Proxy Manager: \e[34mhttp://localhost:6901\n\e[0mphpMyAdmin: \e[34mhttp://localhost:6902\n\e[0mFileBrowser: \e[34mhttp://localhost:6903\e[0m\n\nRun ctop to manage containers and view metrics.\n"' >> /home/$username/.bashrc 157 | echo 'type ~/firewall.sh &>/dev/null && ./firewall.sh'; 158 | } >> /home/"$username"/.bashrc 159 | 160 | # Success Message 161 | echo -e "\n${GREEN}Setup complete 👍. Please log back in as $username on port $ssh_port.${ENDCOLOR}" 162 | echo -e "${GREEN}Firewall script will run on first login.${ENDCOLOR}" 163 | echo -e "${GREEN}Update your SSH config file with the info below${ENDCOLOR}\n" 164 | 165 | echo "Host $(hostname)" 166 | echo " HostName $(curl -s ifconfig.me)" 167 | echo " Port $ssh_port" 168 | echo " User $username" 169 | echo " LocalForward 6900 127.0.0.1:6900" 170 | echo " LocalForward 6901 127.0.0.1:6901" 171 | echo " LocalForward 6902 127.0.0.1:6902" 172 | echo " LocalForward 6903 127.0.0.1:6903" 173 | echo " ServerAliveInterval 60" 174 | echo -e " ServerAliveCountMax 10\n" 175 | 176 | # clean up script 177 | rm ./setup.sh 178 | 179 | # option to reboot 180 | read -r -p "$(echo -e "${CYAN}Do you want to reboot now (y/n)?${ENDCOLOR} ")" yn 181 | if [[ $yn =~ ^[Yy]$ ]]; then 182 | reboot; 183 | fi -------------------------------------------------------------------------------- /systemd/reloadFail2ban.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description="Reload npm-docker Fail2ban jail to add logs for new sites" 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | ExecStart=docker exec fail2ban sh -c "fail2ban-client reload npm-docker" -------------------------------------------------------------------------------- /systemd/reloadFail2ban.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description="Reload npm-docker Fail2ban jail timer" 3 | 4 | [Timer] 5 | OnBootSec=6h 6 | OnUnitActiveSec=6h 7 | Unit=reloadFail2ban.service 8 | 9 | [Install] 10 | WantedBy=multi-user.target 11 | --------------------------------------------------------------------------------