Vaultwarden_Setup_Script/VW_Setup.sh
2021-12-17 23:08:42 +00:00

351 lines
11 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
echo "This Script must be ran as Root"
if [ "$(grep -c "debian" /etc/os-release)" -gt 0 ]; then
echo "Installing Security Packages"
## Basic Server hardening and setup
sudo apt install fail2ban ufw
sudo ufw allow http
sudo ufw allow https
sudo ufw allow ssh
if [ -d "/etc/docker/" ];then
sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo docker run hello-world # < Check for install error
else
echo "Skipping install of Docker (already Installed)"
fi
elif [ "$(grep -c "debian" /etc/os-release)" -gt 0 ]; then
echo "Installing Security Packages"
# Basic Server hardening and setup
sudo apt install fail2ban ufw
sudo ufw allow http
sudo ufw allow https
sudo ufw allow ssh
if [ -d "/etc/docker/" ];then
sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo docker run hello-world
else
echo "Skipping install of Docker (already Installed)"
fi
if [ -d "/etc/docker/" ];then
echo "Installing Docker Compose"
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname - s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version # < Check for install error
else
echo "Skipping install of Docker Compose (Already Installed)"
fi
## Setup folder Sutucture
sudo mkdir /opt/vaultwarden
sudo mkdir /opt/vaultwarden/vw-data
sudo mkdir /opt/vaultwarden/data
sudo mkdir /opt/vaultwarden/data/vaultwarden
sudo mkdir /opt/vaultwarden/data/vaultwarden/db_backup
sudo mkdir /opt/vaultwarden/data/certbot
sudo mkdir /opt/vaultwarden/data/certbot/conf
sudo mkdir /opt/vaultwarden/data/certbot/www
sudo mkdir /opt/vaultwarden/data/nginx
sudo mkdir /opt/vaultwarden/data/ssl
## Input user veriables
echo "Please Specify the Domain Name you would like to use: "
read chosenFQDN
echo "Please Specify the email address you would like to use for LeysEncrypt Certs: "
read chosenEmail
echo "Generating Random Admin Token"
echo "You can also find this in the docker-compose.yml file in /opt/vaultwarden"
wait 5
chosenAdminToken=$(openssl rand -base64 48)
echo "Your Admin Token is: $chosenAdminToken"
echo "Please make a note of this"
read -p "Press enter to continue"
## Create nginx conf
sudo cat <<EOF > /opt/vaultwarden/data/nginx/nginx.conf
http{
## This Server returns a 444 error if the host IP is browsed
server {
listen 80 default_server;
server_name "";
return 444;
}
## This Server is the HTTP Vaultwarden instance
server {
listen 80;
server_name $chosenFQDN;
## The first location returns a redirect to the https site
location / {
return 301 https://$host$request_uri;
}
## The second location is for the acme challenge for LetsEncrypt
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
## This Server returns a 444 error if the host IP is browsed
server {
listen 443 default_server;
server_name "";
return 444;
ssl_certificate /etc/dummyssl/dummycert.pem;
ssl_certificate_key /etc/dummyssl/dummykey.pem;
}
## This Server is the HTTPS Vaultwarden instance
server {
listen 443 ssl;
server_name $chosenFQDN;
ssl_certificate /etc/letsencrypt/live/$chosenFQDN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$chosenFQDN/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
include /etc/nginx/cloudflare;
location / {
proxy_pass http://localhost;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /admin {
proxy_pass http://localhost/admin;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
auth_basic "Administrators Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
}
}
EOF
## Create Lets Encrypt Script
sudo cat <<EOF > /opt/vaultwarden/data/nginx/nginx.conf
#!/bin/bash
if ! [ -x "$(command -v docker-compose)" ]; then
echo 'Error: docker-compose is not installed.' >&2
exit 1
fi
domains=($chosenFQDN)
rsa_key_size=4096
data_path="./data/certbot"
email="$chosenEmail" # Adding a valid address is strongly recommended
staging=1 # Set to 1 if you're testing your setup to avoid hitting request limits
if [ -d "$data_path" ]; then
read -p "Existing data found for $domains. Continue and replace existing certificate? (y/N) " decision
if [ "$decision" != "Y" ] && [ "$decision" != "y" ]; then
exit
fi
fi
if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then
echo "### Downloading recommended TLS parameters ..."
mkdir -p "$data_path/conf"
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf"
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem"
echo
fi
echo "### Creating dummy certificate for $domains ..."
path="/etc/letsencrypt/live/$domains"
mkdir -p "$data_path/conf/live/$domains"
docker-compose run --rm --entrypoint "\
openssl req -x509 -nodes -newkey rsa:$rsa_key_size -days 1\
-keyout '$path/privkey.pem' \
-out '$path/fullchain.pem' \
-subj '/CN=localhost'" certbot
echo
echo "### Starting nginx ..."
docker-compose up --force-recreate -d nginx
echo
echo "### Deleting dummy certificate for $domains ..."
docker-compose run --rm --entrypoint "\
rm -Rf /etc/letsencrypt/live/$domains && \
rm -Rf /etc/letsencrypt/archive/$domains && \
rm -Rf /etc/letsencrypt/renewal/$domains.conf" certbot
echo
echo "### Requesting Let's Encrypt certificate for $domains ..."
##Join $domains to -d args
domain_args=""
for domain in "${domains[@]}"; do
domain_args="$domain_args -d $domain"
done
## Select appropriate email arg
case "$email" in
"") email_arg="--register-unsafely-without-email" ;;
*) email_arg="--email $email" ;;
esac
## Enable staging mode if needed
if [ $staging != "0" ]; then staging_arg="--staging"; fi
docker-compose run --rm --entrypoint "\
certbot certonly --webroot -w /var/www/certbot \
$staging_arg \
$email_arg \
$domain_args \
--rsa-key-size $rsa_key_size \
--agree-tos \
--force-renewal" certbot
echo
echo "### Reloading nginx ..."
docker-compose exec nginx nginx -s reload
EOF
# Create cloudflare-update-ip-ranges script
sudo cat <<EOF > /opt/vaultwarden/cloudflare-update-ip-ranges.sh
#!/bin/bash
# Location of the nginx config file that contains the CloudFlare IP addresses.
CF_NGINX_CONFIG="/opt/vaultwarden/data/nginx/cloudflare"
# The URLs with the actual IP addresses used by CloudFlare.
CF_URL_IP4="https://www.cloudflare.com/ips-v4"
CF_URL_IP6="https://www.cloudflare.com/ips-v6"
# Temporary files.
CF_TEMP_IP4="/tmp/cloudflare-ips-v4.txt"
CF_TEMP_IP6="/tmp/cloudflare-ips-v6.txt"
# Download the files.
if [ -f /usr/bin/curl ];
then
curl --silent --output $CF_TEMP_IP4 $CF_URL_IP4
curl --silent --output $CF_TEMP_IP6 $CF_URL_IP6
elif [ -f /usr/bin/wget ];
then
wget --quiet --output-document=$CF_TEMP_IP4 --no-check-certificate $CF_URL_IP4
wget --quiet --output-document=$CF_TEMP_IP6 --no-check-certificate $CF_URL_IP6
else
echo "Unable to download CloudFlare files."
exit 1
fi
# Generate the new config file.
echo "# CloudFlare IP Ranges" > $CF_NGINX_CONFIG
echo "# Generated at $(date) by $0" >> $CF_NGINX_CONFIG
echo "" >> $CF_NGINX_CONFIG
echo "# - IPv4 ($CF_URL_IP4)" >> $CF_NGINX_CONFIG
awk '{ print "set_real_ip_from " $0 ";" }' $CF_TEMP_IP4 >> $CF_NGINX_CONFIG
echo "" >> $CF_NGINX_CONFIG
echo "# - IPv6 ($CF_URL_IP6)" >> $CF_NGINX_CONFIG
awk '{ print "set_real_ip_from " $0 ";" }' $CF_TEMP_IP6 >> $CF_NGINX_CONFIG
echo "" >> $CF_NGINX_CONFIG
echo "real_ip_header CF-Connecting-IP;" >> $CF_NGINX_CONFIG
echo "" >> $CF_NGINX_CONFIG
# Remove the temporary files.
rm $CF_TEMP_IP4 $CF_TEMP_IP6
# Reload the nginx config.
cd /opt/vaultwarden
docker-compose restart
EOF
# Create Docker-compose.yml
sudo cat <<EOF > /opt/vaultwarden/docker-compose.yml
version: '3'
services:
vaultwarden:
image: vaultwardenrs/server
hostname: vaultwarden
restart: always
expose:
- "80"
volumes:
- ./vw-data:/data
environment:
WEBSOCKET_ENABLED: 'true'
SIGNUPS_ALLOWED: 'false'
ADMIN_TOKEN: "$chosenAdminToken"
LOG_FILE: ./data/vaultwarden.log
nginx:
image: nginx:1.15-alpine
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx:/etc/nginx
- ./data/ssl:/etc/ssl
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
bw_backup:
image: bruceforce/bw_backup:latest
container_name: bw_backup
restart: on-failure
depends_on:
- vaultwarden
volumes:
- ./data/vaultwarden:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
- DB_FILE=/data/db.sqlite3
- BACKUP_FILE=/data/db_backup/bwbackup.sqlite3
- CRON_TIME= 10 * * * *
- TIMESTAMP=true
- UID=0
- GID=0
- ./data/ssl:/etc/ssl
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
certbot:
image: certbot/certbot
restart: always
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
EOF
else
echo "Sorry, this OS is not Debian or Ubuntu based."
fi