Last active
May 23, 2018 18:41
-
-
Save brickpop/01f4229f3506ea5bd5f02c1dcafce880 to your computer and use it in GitHub Desktop.
Debian Jessie Server setup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Vanilla Debian Jessie Setup | |
sudo su - | |
# DEBIAN JESSIE SETUP SCRIPT | |
# ------------------------------------------------------------------------- | |
# VARIABLES | |
# ------------------------------------------------------------------------- | |
HOSTNAME="my-host" | |
NODE_VERSION="v8.11.2" | |
USE_SWAP=true # USE_SWAP= >> false | |
USE_NGINX=true | |
USE_MONGO=true | |
USE_CERTBOT=true | |
USE_BACKUP=true | |
# ------------------------------------------------------------------------- | |
# MAIN | |
# ------------------------------------------------------------------------- | |
echo $HOSTNAME > /etc/hostname | |
apt-get update | |
apt-get -y dist-upgrade | |
apt-get install -y vim git | |
# ------------------------------------------------------------------------- | |
# NODE | |
# ------------------------------------------------------------------------- | |
curl -LO http://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-x64.tar.gz | |
tar xzf node-$NODE_VERSION-linux-x64.tar.gz | |
cp -R ./node-$NODE_VERSION-linux-x64/bin/* /usr/local/bin | |
cp -R ./node-$NODE_VERSION-linux-x64/lib/* /usr/local/lib | |
cp -R ./node-$NODE_VERSION-linux-x64/include/* /usr/local/include | |
cp -R ./node-$NODE_VERSION-linux-x64/share/* /usr/local/share | |
rm -Rf ./node-$NODE_VERSION-linux-x64* | |
# NODE UPDATER | |
npm install -g n | |
# ------------------------------------------------------------------------- | |
# APP USER | |
# ------------------------------------------------------------------------- | |
useradd -m -d /home/app -s /bin/bash -c "App Server" app | |
# SSH AUTHORIZED KEYS | |
su -c "mkdir /home/app/.ssh" app | |
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0ffDG7xoQsh6QUOKKEvg5jrCtV+Zwc0bEh72u+15gPZ5nf7yoMVxJO6BInPhDEIAPa8L58l38qElwGr5POwPkR2hKZpg1Vletq3so6BYP3jj+NTm+rPsSJImpq7hyJfgKUbfSlZrK9M5rHnIIx8YNAsjJymOEAwZowggOwvNXELYlDEeIgkr729z5Ek78CR5uSFp9bXfC63CcWjEURp8kzH+tBFMbEpX8xmZeHv9xvpMs36LS+9yuWTfnGq3ufQHkiohuR/BkSqoMJsS+cgVn1y+rl1usfBfi+bsb8IOsOoo9luKC+/69dSACW4sEDrYukOy6dlERXK9paCcutdK/ [email protected]" > /home/app/.ssh/authorized_keys | |
# root owned, yes I know | |
# ------------------------------------------------------------------------- | |
# DOT FILES | |
# ------------------------------------------------------------------------- | |
cat <<EOF >> /tmp/profile.opts | |
# colorful grep | |
export GREP_OPTIONS='--color=auto' | |
EOF | |
cat /tmp/profile.opts >> /root/.profile | |
cat /tmp/profile.opts >> /home/app/.profile | |
rm /tmp/profile.opts | |
# ------------------------------------------------------------------- | |
cat <<'EOF' >> /tmp/bashrc.opts | |
# command aliases | |
alias l='ls -lhF' | |
alias la='ls -lhFa' | |
# diff for developers | |
alias mydiff='diff -u --show-c-function -s $1 $2' | |
# custom shell | |
PS1="\[\033[0;37m\]\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[0;31m\]root@$HOSTNAME'; else echo '\[\033[0;33m\]\u\[\033[0;37m\]@\[\033[0;96m\]$HOSTNAME'; fi)\[\033[0;37m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;37m\]]\n\[\033[0;37m\]$ \[\033[0m\]" | |
EOF | |
cat /tmp/bashrc.opts >> /root/.bashrc | |
cat /tmp/bashrc.opts >> /home/app/.bashrc | |
rm /tmp/bashrc.opts | |
# ------------------------------------------------------------------- | |
cat <<EOF >> /tmp/vimrc | |
" Syntax Highlighting | |
:syn on | |
" Clearer color scheme | |
":colo elflord | |
" Use 2 spaces per tab | |
:set tabstop=2 | |
" Expand tabs into spaces | |
:set expandtab | |
" Highlight search occurrences | |
:set hlsearch | |
" Last status | |
:set ls=2 | |
" Display the file name, line ending format, | |
" column, line, total lines and the current command | |
:set statusline=%f%=[%{&ff}]\ [C%v,L%l/%L] | |
EOF | |
cat /tmp/vimrc > /root/.vimrc | |
cat /tmp/vimrc > /home/app/.vimrc | |
chown app:app /home/app/.vimrc | |
rm /tmp/vimrc | |
# ------------------------------------------------------------------------- | |
# ENV VARIABLES | |
# ------------------------------------------------------------------------- | |
su -c "echo 'export NODE_ENV=production' > /home/app/ENV" app | |
echo "source /home/app/ENV" >> /home/app/.bashrc | |
# ------------------------------------------------------------------------- | |
# PM2 | |
# ------------------------------------------------------------------------- | |
npm install -g pm2 | |
su -c "pm2 list" app | |
pm2 startup systemd -u app --hp /home/app | |
# ------------------------------------------------------------------------- | |
# SWAP | |
# ------------------------------------------------------------------------- | |
if [ $USE_SWAP ] | |
then | |
dd if=/dev/zero of=/swapfile1 bs=4096 count=1048576 | |
chown root:root /swapfile1 | |
chmod 0600 /swapfile1 | |
mkswap /swapfile1 | |
swapon /swapfile1 | |
echo "/swapfile1 none swap sw 0 0" >> /etc/fstab | |
fi | |
# ------------------------------------------------------------------------- | |
# IPTABLES | |
# ------------------------------------------------------------------------- | |
cat <<EOF > /etc/iptables.init.rules | |
*filter | |
# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0 | |
-A INPUT -i lo -j ACCEPT | |
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT | |
# Accepts all established inbound connections | |
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | |
# Allows all outbound traffic | |
# You could modify this to only allow certain traffic | |
-A OUTPUT -j ACCEPT | |
# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites) | |
-A INPUT -p tcp --dport 80 -j ACCEPT | |
-A INPUT -p tcp --dport 443 -j ACCEPT | |
# Allows SSH connections | |
# The --dport number is the same as in /etc/ssh/sshd_config | |
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT | |
# Now you should read up on iptables rules and consider whether ssh access | |
# for everyone is really desired. Most likely you will only allow access from certain IPs. | |
# Allow ping | |
# note that blocking other types of icmp packets is considered a bad idea by some | |
# remove -m icmp --icmp-type 8 from this line to allow all kinds of icmp: | |
# https://security.stackexchange.com/questions/22711 | |
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT | |
# log iptables denied calls (access via 'dmesg' command) | |
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 | |
# Reject all other inbound - default deny unless explicitly allowed policy: | |
-A INPUT -j REJECT | |
-A FORWARD -j REJECT | |
COMMIT | |
EOF | |
iptables-restore < /etc/iptables.init.rules | |
iptables-save > /etc/iptables.up.rules | |
cat <<EOF > /etc/network/if-pre-up.d/iptables | |
#!/bin/sh | |
/sbin/iptables-restore < /etc/iptables.up.rules | |
EOF | |
chmod +x /etc/network/if-pre-up.d/iptables | |
# ------------------------------------------------------------------------- | |
# IP6 TABLES | |
# ------------------------------------------------------------------------- | |
cat <<EOF > /etc/ip6tables.init.rules | |
*filter | |
# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0 | |
-A INPUT -i lo -j ACCEPT | |
-A INPUT ! -i lo -d ::1 -j REJECT | |
# Accepts all established inbound connections | |
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | |
# Allows all outbound traffic | |
# You could modify this to only allow certain traffic | |
-A OUTPUT -j ACCEPT | |
# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites) | |
-A INPUT -p tcp --dport 80 -j ACCEPT | |
-A INPUT -p tcp --dport 443 -j ACCEPT | |
# Allows SSH connections | |
# The --dport number is the same as in /etc/ssh/sshd_config | |
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT | |
# Now you should read up on ip6tables rules and consider whether ssh access | |
# for everyone is really desired. Most likely you will only allow access from certain IPs. | |
# log ip6tables denied calls (access via 'dmesg' command) | |
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "ip6tables denied: " --log-level 7 | |
# Reject all other inbound - default deny unless explicitly allowed policy: | |
-A INPUT -j REJECT | |
-A FORWARD -j REJECT | |
COMMIT | |
EOF | |
ip6tables-restore < /etc/ip6tables.init.rules | |
ip6tables-save > /etc/ip6tables.up.rules | |
cat <<EOF > /etc/network/if-pre-up.d/ip6tables | |
#!/bin/sh | |
/sbin/ip6tables-restore < /etc/ip6tables.up.rules | |
EOF | |
chmod +x /etc/network/if-pre-up.d/ip6tables | |
# ------------------------------------------------------------------------- | |
# NGINX SERVER | |
# ------------------------------------------------------------------------- | |
if [ $USE_NGINX ] | |
then | |
apt-get install -y nginx | |
# DH KEYS | |
openssl dhparam -out dhparams.pem 2048 | |
mv dhparams.pem /etc/ssl | |
# DEFAULT SITE | |
cat <<EOF > /var/www/html/index.html | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Welcome</title> | |
</head> | |
<body></body> | |
</html> | |
EOF | |
rm /var/www/html/index.nginx-debian.html | |
# EXAMPLE VIRTUAL HOST | |
cat <<'EOF' > /etc/nginx/sites-available/example-virtual-host | |
# TO DO | |
# - Replace 'my-host.com' by your actual domain | |
# - Replace '9000' with your local port | |
# - Run certbot to geherate a certificate for your domain and uncoment the HTTPS section below | |
# $ certbot certonly --webroot -w /var/www/certbot -d www.my-host.com -d my-host.com | |
# | |
upstream app-server { | |
ip_hash; | |
server localhost:9000; | |
# server localhost:9001; # used if clustering is available | |
} | |
# | |
# HTTPS | |
# | |
# server { | |
# listen 443 ssl; | |
# listen [::]:443 ssl; | |
# server_name my-host.com; | |
# | |
# ssl_certificate /etc/letsencrypt/live/my-host.com/fullchain.pem; | |
# ssl_certificate_key /etc/letsencrypt/live/my-host.com/privkey.pem; | |
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2; | |
# ssl_ciphers HIGH:!aNULL:!MD5; | |
# ssl_prefer_server_ciphers on; | |
# ssl_dhparam /etc/ssl/dhparams.pem; | |
# | |
# gzip on; | |
# gzip_proxied any; | |
# gzip_types | |
# text/css | |
# text/javascript | |
# text/xml | |
# text/plain | |
# image/svg+xml | |
# application/javascript | |
# application/x-javascript | |
# application/json; | |
# | |
# # Longer cache | |
# location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ { | |
# expires 6d; | |
# access_log off; | |
# add_header Cache-Control "public"; | |
# | |
# proxy_set_header X-Real-IP $remote_addr; | |
# proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
# proxy_set_header Host $http_host; | |
# proxy_set_header X-NginX-Proxy true; | |
# | |
# proxy_pass http://app-server; | |
# | |
# proxy_http_version 1.1; | |
# proxy_set_header Upgrade $http_upgrade; | |
# proxy_set_header Connection "upgrade"; | |
# | |
# error_page 502 = /502.html; | |
# error_page 501 503 504 505 = /505.html; | |
# } | |
# | |
# # Shorter cache | |
# location ~* \.(?:css|js)$ { | |
# expires 2d; | |
# access_log off; | |
# add_header Cache-Control "public"; | |
# | |
# proxy_set_header X-Real-IP $remote_addr; | |
# proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
# proxy_set_header Host $http_host; | |
# proxy_set_header X-NginX-Proxy true; | |
# | |
# proxy_pass http://app-server; | |
# | |
# proxy_http_version 1.1; | |
# proxy_set_header Upgrade $http_upgrade; | |
# proxy_set_header Connection "upgrade"; | |
# | |
# error_page 502 = /502.html; | |
# error_page 501 503 504 505 = /505.html; | |
# } | |
# | |
# location /api { | |
# expires 0s; | |
# | |
# proxy_set_header X-Real-IP $remote_addr; | |
# proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
# proxy_set_header Host $http_host; | |
# proxy_set_header X-NginX-Proxy true; | |
# proxy_pass http://app-server; | |
# proxy_http_version 1.1; | |
# | |
# proxy_set_header Upgrade $http_upgrade; | |
# proxy_set_header Connection "upgrade"; | |
# } | |
# | |
# location / { | |
# proxy_set_header X-Real-IP $remote_addr; | |
# proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
# proxy_set_header Host $http_host; | |
# proxy_set_header X-NginX-Proxy true; | |
# | |
# proxy_pass http://app-server; | |
# | |
# proxy_http_version 1.1; | |
# proxy_set_header Upgrade $http_upgrade; | |
# proxy_set_header Connection "upgrade"; | |
# | |
# error_page 502 = /502.html; | |
# error_page 501 503 504 505 = /505.html; | |
# } | |
# location /502.html { | |
# root /usr/share/nginx/html; | |
# } | |
# location /505.html { | |
# root /usr/share/nginx/html; | |
# } | |
# } | |
# HTTP | |
server { | |
listen 80; | |
listen [::]:80; | |
server_name my-host.com; | |
gzip on; | |
gzip_proxied any; | |
gzip_types | |
text/css | |
text/javascript | |
text/xml | |
text/plain | |
image/svg+xml | |
application/javascript | |
application/x-javascript | |
application/json; | |
# Longer cache | |
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ { | |
expires 6d; | |
access_log off; | |
add_header Cache-Control "public"; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-NginX-Proxy true; | |
proxy_pass http://app-server; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
error_page 502 = /502.html; | |
error_page 501 503 504 505 = /505.html; | |
} | |
# Shorter cache | |
location ~* \.(?:css|js)$ { | |
expires 3d; | |
access_log off; | |
add_header Cache-Control "public"; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-NginX-Proxy true; | |
proxy_pass http://app-server; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
error_page 502 = /502.html; | |
error_page 501 503 504 505 = /505.html; | |
} | |
location /api { | |
expires 0s; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-NginX-Proxy true; | |
proxy_pass http://app-server; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
} | |
location / { | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-NginX-Proxy true; | |
proxy_pass http://app-server; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
error_page 502 = /502.html; | |
error_page 501 503 504 505 = /505.html; | |
# When HTTPS is ready: | |
# return 301 https://www.my-host.com$request_uri; | |
} | |
location /.well-known { | |
root /var/www/certbot; | |
} | |
location /502.html { | |
root /usr/share/nginx/html; | |
} | |
location /505.html { | |
root /usr/share/nginx/html; | |
} | |
} | |
EOF | |
# SERVICE UNAVAILABLE PAGE | |
cat <<EOF > /usr/share/nginx/html/502.html | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Service unavailable</title> | |
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> | |
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> | |
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> | |
<style> | |
body { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMC8yOS8xMiKqq3kAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzVxteM2AAABHklEQVRIib2Vyw6EIAxFW5idr///Qx9sfG3pLEyJ3tAwi5EmBqRo7vHawiEEERHS6x7MTMxMVv6+z3tPMUYSkfTM/R0fEaG2bbMv+Gc4nZzn+dN4HAcREa3r+hi3bcuu68jLskhVIlW073tWaYlQ9+F9IpqmSfq+fwskhdO/AwmUTJXrOuaRQNeRkOd5lq7rXmS5InmERKoER/QMvUAPlZDHcZRhGN4CSeGY+aHMqgcks5RrHv/eeh455x5KrMq2yHQdibDO6ncG/KZWL7M8xDyS1/MIO0NJqdULLS81X6/X6aR0nqBSJcPeZnlZrzN477NKURn2Nus8sjzmEII0TfMiyxUuxphVWjpJkbx0btUnshRihVv70Bv8ItXq6Asoi/ZiCbU6YgAAAABJRU5ErkJggg==);} | |
.error-template {padding: 40px 15px;text-align: center;} | |
.error-actions {margin-top:15px;margin-bottom:15px;} | |
.error-actions .btn { margin-right:10px; } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-12"> | |
<div class="error-template"> | |
<h1>Ooops</h1> | |
<div class="error-details"> | |
The service you are trying to access is currently off line. | |
</div> | |
<div class="error-actions"> | |
<a href="http://www.tvrbo.pro" class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-home"></span> Take me Home</a> | |
<a href="mailto:[email protected]?subject=Unavailable" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-envelope"></span> Contact support</a> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> | |
EOF | |
# SERVER ERROR PAGE | |
cat <<EOF > /usr/share/nginx/html/505.html | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Error</title> | |
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> | |
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> | |
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> | |
<style> | |
body { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMC8yOS8xMiKqq3kAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzVxteM2AAABHklEQVRIib2Vyw6EIAxFW5idr///Qx9sfG3pLEyJ3tAwi5EmBqRo7vHawiEEERHS6x7MTMxMVv6+z3tPMUYSkfTM/R0fEaG2bbMv+Gc4nZzn+dN4HAcREa3r+hi3bcuu68jLskhVIlW073tWaYlQ9+F9IpqmSfq+fwskhdO/AwmUTJXrOuaRQNeRkOd5lq7rXmS5InmERKoER/QMvUAPlZDHcZRhGN4CSeGY+aHMqgcks5RrHv/eeh455x5KrMq2yHQdibDO6ncG/KZWL7M8xDyS1/MIO0NJqdULLS81X6/X6aR0nqBSJcPeZnlZrzN477NKURn2Nus8sjzmEII0TfMiyxUuxphVWjpJkbx0btUnshRihVv70Bv8ItXq6Asoi/ZiCbU6YgAAAABJRU5ErkJggg==);} | |
.error-template {padding: 40px 15px;text-align: center;} | |
.error-actions {margin-top:15px;margin-bottom:15px;} | |
.error-actions .btn { margin-right:10px; } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-12"> | |
<div class="error-template"> | |
<h1>Ooops</h1> | |
<div class="error-details"> | |
The server has encountered an internal error and is unable to fulfill your request at this time. | |
</div> | |
<div class="error-actions"> | |
<a href="http://www.tvrbo.pro" class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-home"></span> Take me Home</a> | |
<a href="mailto:[email protected]?subject=Error" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-envelope"></span> Contact support</a> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> | |
EOF | |
service nginx start | |
fi | |
# ------------------------------------------------------------------------- | |
# MONGODB | |
# ------------------------------------------------------------------------- | |
if [ $USE_MONGO ] | |
then | |
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 | |
echo "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/3.4 main" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list | |
apt-get update | |
apt-get install -y mongodb-org | |
service mongod start | |
fi | |
# ------------------------------------------------------------------------- | |
# CERTBOT | |
# ------------------------------------------------------------------------- | |
if [ $USE_CERTBOT ] | |
then | |
apt-get install -y certbot -t jessie-backports | |
apt-get install -y python-certbot-nginx | |
# certbot --nginx | |
# certbot --authenticator webroot --installer nginx --webroot-path /var/www/certbot | |
cat <<'EOF' > /etc/cron.weekly/certbot-renew | |
#!/bin/bash | |
LOG=/root/certbot-renew.log | |
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | |
echo "-----------------------------------" >> $LOG | |
echo "STARTING CERTBOT RENEW" >> $LOG | |
date "+%Y/%m/%d %H:%M:%S" >> $LOG | |
if [ ! -x /usr/bin/certbot ] | |
then | |
echo "Unrunable script" >> $LOG | |
exit 1 | |
fi | |
/usr/bin/perl -e 'sleep int(rand(300))' | |
#/usr/bin/certbot -q renew >> $LOG | |
echo "RUNNING CERTBOT" >> $LOG | |
/usr/bin/certbot renew >> $LOG | |
if [ $? == 0 ] | |
then | |
echo "RELOADING NGINX" >> $LOG | |
/usr/sbin/service nginx reload >> $LOG | |
else | |
echo "CERTBOT ERROR - Will not reload Nginx" >> $LOG | |
fi | |
EOF | |
chmod 755 /etc/cron.weekly/certbot-renew | |
mkdir /var/www/certbot | |
fi | |
# ------------------------------------------------------------------------- | |
# BACKUPS | |
# ------------------------------------------------------------------------- | |
if [ $USE_BACKUP ] | |
then | |
echo "ADDING BACKUP FACILITIES" | |
cd /root | |
mkdir backup | |
cd /root/backup | |
npm install gcloud-backup-toolset shelljs @google-cloud/storage bluebird | |
cat <<'EOF' > /root/backup/backup.js | |
#!/usr/bin/env node | |
const config = require('./config.js'); | |
const lib = require('gcloud-backup-toolset'); | |
require('shelljs/global'); | |
var configuration = { | |
gCloudProjectId: config.gCloudProjectId, | |
gCloudKeyFilename: config.gCloudKeyFilename, | |
gCloudBucket: config.gCloudKeyFilename, | |
bucketSubdir: config.gCloudKeyFilename | |
}; | |
if(config.aesKey) | |
configuration.aesKey = config.aesKey; | |
function log(...args) { | |
console.log(new Date().toJSON(), "|", ...args, "\n"); | |
} | |
log("STARTING BACKUP", config.gCloudProjectId, config.backupName); | |
lib.doBackup(configuration, config.backupName, (tmpDir, report) => { | |
// copy files into tmpDir | |
// report is a report object you can use for logs and error | |
log(`The working folder is ${tmpDir}`); | |
cd(tmpDir); | |
log("DUMPING THE DATABASE"); | |
exec(`mongodump --db ${config.databaseName}`); | |
}) | |
.then((report)=>{ | |
log("BACKUP COMPLETE", config.gCloudProjectId, config.backupName); | |
log(report.toString()) | |
}) | |
.catch(err => { | |
log("BACKUP ERROR", err.message); | |
log(err); | |
}); | |
EOF | |
cat <<'EOF' > /root/backup/config.js | |
module.exports = { | |
gCloudProjectId: "my-app-id", | |
gCloudKeyFilename: __dirname + '/gcloud.json', | |
gCloudBucket: "my-app-backup", | |
bucketSubdir: "mongodb-backup", | |
//aesKey: "LOzKM6wlcd3NlSPjoEXfSbJimJXtwtLgGawTLjCpzHoTQMcHX4xN9YX97KRjNEO1", | |
databaseName: 'db-name', | |
backupName: 'weekly', | |
backupCopies: 5 | |
}; | |
EOF | |
cat <<'EOF' > /root/backup/rotate.js | |
#!/usr/bin/env node | |
const config = require('./config.js'); | |
const storage = require('@google-cloud/storage'); | |
const bluebird = require("bluebird"); | |
function log(...args) { | |
console.log(new Date().toJSON(), "|", ...args, "\n"); | |
} | |
var gcs = storage({ | |
projectId: config.gCloudProjectId, | |
keyFilename: config.gCloudKeyFilename | |
}); | |
log("STARTING ROTATION", config.gCloudProjectId, config.backupName); | |
const bucket = gcs.bucket(config.gCloudBucket); | |
// Remove old backups | |
listFiles(bucket, config.bucketSubdir).then(files => { | |
log(`GOT ${files.length} FILES`); | |
if(!files || files.length < config.backupCopies) return; | |
files = files.sort((file1, file2) => file2.metadata.timeCreated.localeCompare(file1.metadata.timeCreated)); | |
files = files.filter(file => parseInt(file.metadata.size)>0) | |
const cleanable = files.slice(config.backupCopies); | |
log(`CLEANING THE OLDEST ${cleanable.length}`); | |
return bluebird.map(cleanable, file => { | |
log('Cleaning', file.name); | |
return bucket.file(file.name).delete(); | |
}) | |
}) | |
.then(result => { | |
log("DONE", config.gCloudProjectId, config.backupName); | |
}) | |
.catch(err => { | |
log("ERROR: UNABLE TO ROTATE", err); | |
}); | |
// AUX | |
function listFiles(bucket, prefix) { | |
return new bluebird.Promise((resolve, reject) => { | |
var list = []; | |
function readResponse(err, files, nextQuery, apiResponse) { | |
if (err) return reject(err); | |
list = list.concat(files); | |
if (nextQuery) bucket.getFiles(nextQuery, readResponse); | |
else resolve(list); | |
} | |
bucket.getFiles({ | |
maxResults: 50, | |
prefix: prefix | |
}, readResponse); | |
}); | |
} | |
EOF | |
cat <<'EOF' > /root/backup/TO-DO | |
1) Sign up on https://console.developers.google.com/apis?project=right-side-coffee | |
2) Create a project | |
3) Go to Credentials > Create Credentials > Service Account Key | |
4) Generate a JSON key file | |
5) Put it in this folder | |
6) Update the config.js file to match your environment | |
EOF | |
cat <<'EOF' > /etc/cron.weekly/backup | |
#!/bin/bash | |
LOG=/root/backup/weekly.log | |
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | |
echo "-----------------------------------" >> $LOG | |
echo "STARTING WEEKLY BACKUP" >> $LOG | |
date "+%Y/%m/%d %H:%M:%S" >> $LOG | |
if [ ! -x /root/backup/backup.js ] | |
then | |
echo "Unrunable script" >> $LOG | |
exit 1 | |
fi | |
echo "RUNNING BACKUP" >> $LOG | |
/root/backup/backup.js >> $LOG 2>&1 | |
echo "RUNNING ROTATE" >> $LOG | |
/root/backup/rotate.js >> $LOG 2>&1 | |
echo "DONE" >> $LOG | |
EOF | |
# PERMISSIONS | |
chmod 755 backup.js rotate.js /etc/cron.weekly/backup | |
fi | |
# ------------------------------------------------------------------------ | |
# OPTIONAL | |
# ------------------------------------------------------------------------- | |
#hostname my-host.com # set your domain | |
sudo apt-get install exim4 | |
dpkg-reconfigure exim4-config | |
# set up | |
# https://www.digitalocean.com/community/tutorials/how-to-install-the-send-only-mail-server-exim-on-ubuntu-12-04 | |
# ------------------------------------------------------------------------ | |
# DONE | |
# ------------------------------------------------------------------------- | |
reboot |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Amazon Debian Jessie AMI | |
# debian-jessie-amd64-hvm-2017-01-15-1221-ebs | |
# | |
# Useful for a Launch Configuration Script | |
# ------------------------------------------------------------------------- | |
# VARIABLES | |
# ------------------------------------------------------------------------- | |
NODE_VERSION="v8.11.2" | |
USE_SWAP=true # USE_SWAP= >> false | |
USE_NODEJS=true | |
USE_NGINX= | |
USE_MONGO= | |
USE_CERTBOT= | |
USE_BACKUP= | |
# ------------------------------------------------------------------------- | |
# MAIN | |
# ------------------------------------------------------------------------- | |
sudo apt-get update | |
sudo apt-get -y dist-upgrade | |
sudo apt-get install -y vim git | |
# ------------------------------------------------------------------------- | |
# NODE | |
# ------------------------------------------------------------------------- | |
if [ $USE_NODEJS ] | |
then | |
curl -LO http://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-x64.tar.gz | |
tar xzf node-$NODE_VERSION-linux-x64.tar.gz | |
sudo cp -R ./node-$NODE_VERSION-linux-x64/bin/* /usr/local/bin | |
sudo cp -R ./node-$NODE_VERSION-linux-x64/lib/* /usr/local/lib | |
sudo cp -R ./node-$NODE_VERSION-linux-x64/include/* /usr/local/include | |
sudo cp -R ./node-$NODE_VERSION-linux-x64/share/* /usr/local/share | |
rm -Rf ./node-$NODE_VERSION-linux-x64* | |
# NODE UPDATER | |
sudo npm install -g n | |
fi | |
# ------------------------------------------------------------------------- | |
# APP USER (unprivileged) | |
# ------------------------------------------------------------------------- | |
sudo useradd -m -d /home/app -s /bin/bash -c "App Server" app | |
# SSH AUTHORIZED KEYS | |
sudo su -c "mkdir /home/app/.ssh" app | |
sudo echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0ffDG7xoQsh6QUOKKEvg5jrCtV+Zwc0bEh72u+15gPZ5nf7yoMVxJO6BInPhDEIAPa8L58l38qElwGr5POwPkR2hKZpg1Vletq3so6BYP3jj+NTm+rPsSJImpq7hyJfgKUbfSlZrK9M5rHnIIx8YNAsjJymOEAwZowggOwvNXELYlDEeIgkr729z5Ek78CR5uSFp9bXfC63CcWjEURp8kzH+tBFMbEpX8xmZeHv9xvpMs36LS+9yuWTfnGq3ufQHkiohuR/BkSqoMJsS+cgVn1y+rl1usfBfi+bsb8IOsOoo9luKC+/69dSACW4sEDrYukOy6dlERXK9paCcutdK/ [email protected]" > /home/app/.ssh/authorized_keys | |
# root owned, yes I know | |
# ------------------------------------------------------------------------- | |
# DOT FILES | |
# ------------------------------------------------------------------------- | |
cat <<EOF >> /tmp/profile.opts | |
# colorful grep | |
export GREP_OPTIONS='--color=auto' | |
EOF | |
cat /tmp/profile.opts | sudo tee -a /root/.profile | |
cat /tmp/profile.opts | sudo tee -a /home/admin/.profile | |
cat /tmp/profile.opts | sudo tee -a /home/app/.profile | |
rm /tmp/profile.opts | |
# ------------------------------------------------------------------- | |
cat <<'EOF' >> /tmp/bashrc.opts | |
# command aliases | |
alias l='ls -lhF' | |
alias la='ls -lhFa' | |
# diff for developers | |
alias mydiff='diff -u --show-c-function -s $1 $2' | |
# custom shell | |
PS1="\[\033[0;37m\]\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[0;31m\]root@$HOSTNAME'; else echo '\[\033[0;33m\]\u\[\033[0;37m\]@\[\033[0;96m\]$HOSTNAME'; fi)\[\033[0;37m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;37m\]]\n\[\033[0;37m\]$ \[\033[0m\]" | |
EOF | |
cat /tmp/bashrc.opts | sudo tee -a /root/.bashrc | |
cat /tmp/bashrc.opts | sudo tee -a /home/admin/.bashrc | |
cat /tmp/bashrc.opts | sudo tee -a /home/app/.bashrc | |
# chown admin:admin /home/admin/.bashrc | |
sudo chown app:app /home/app/.bashrc | |
rm /tmp/bashrc.opts | |
# ------------------------------------------------------------------- | |
cat <<EOF >> /tmp/vimrc | |
" Syntax Highlighting | |
:syn on | |
" Clearer color scheme | |
":colo elflord | |
" Use 2 spaces per tab | |
:set tabstop=2 | |
" Expand tabs into spaces | |
:set expandtab | |
" Highlight search occurrences | |
:set hlsearch | |
" Last status | |
:set ls=2 | |
" Display the file name, line ending format, | |
" column, line, total lines and the current command | |
:set statusline=%f%=[%{&ff}]\ [C%v,L%l/%L] | |
EOF | |
cat /tmp/vimrc | sudo tee -a /root/.vimrc | |
cat /tmp/vimrc | sudo tee -a /home/admin/.vimrc | |
cat /tmp/vimrc | sudo tee -a /home/app/.vimrc | |
sudo chown admin:admin /home/admin/.vimrc | |
sudo chown app:app /home/app/.vimrc | |
rm /tmp/vimrc | |
# ------------------------------------------------------------------------- | |
# ENV VARIABLES | |
# ------------------------------------------------------------------------- | |
sudo su -c "echo 'export NODE_ENV=production' > /home/app/ENV" app | |
echo "source /home/app/ENV" | sudo tee -a /home/app/.bashrc | |
# ------------------------------------------------------------------------- | |
# PM2 | |
# ------------------------------------------------------------------------- | |
if [ $USE_NODEJS ] | |
then | |
sudo npm install -g pm2 | |
sudo su -c "pm2 list" app | |
sudo pm2 startup systemd -u app --hp /home/app | |
fi | |
# ------------------------------------------------------------------------- | |
# SWAP | |
# ------------------------------------------------------------------------- | |
if [ $USE_SWAP ] | |
then | |
sudo dd if=/dev/zero of=/swapfile1 bs=2048 count=1048576 | |
sudo chown root:root /swapfile1 | |
sudo chmod 0600 /swapfile1 | |
sudo mkswap /swapfile1 | |
sudo swapon /swapfile1 | |
sudo echo "/swapfile1 none swap sw 0 0" >> /etc/fstab | |
fi | |
# ------------------------------------------------------------------------- | |
# NGINX SERVER | |
# ------------------------------------------------------------------------- | |
if [ $USE_NGINX ] | |
then | |
cd /tmp | |
wget http://nginx.org/keys/nginx_signing.key | |
sudo apt-key add nginx_signing.key | |
rm nginx_signing.key | |
cat <<EOF | sudo tee -a /etc/apt/sources.list.d/nginx.list | |
deb http://nginx.org/packages/mainline/debian/ jessie nginx | |
deb-src http://nginx.org/packages/mainline/debian/ jessie nginx | |
EOF | |
sudo apt-get update | |
sudo apt-get install -y nginx | |
sudo systemctl enable nginx.service | |
# DH KEYS | |
sudo openssl dhparam -out dhparams.pem 2048 | |
sudo mv dhparams.pem /etc/ssl | |
# DEFAULT SITE | |
sudo cat <<EOF > /var/www/html/index.html | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Welcome</title> | |
</head> | |
<body></body> | |
</html> | |
EOF | |
sudo rm /var/www/html/index.nginx-debian.html | |
# EXAMPLE VIRTUAL HOST | |
sudo cat <<'EOF' > /etc/nginx/sites-available/example-virtual-host | |
# TO DO | |
# - Replace 'my-host.com' by your actual domain | |
# - Replace '9000' with your local port | |
# - Run certbot to geherate a certificate for your domain and uncoment the HTTPS section below | |
# $ certbot certonly --webroot -w /var/www/certbot -d www.my-host.com -d my-host.com | |
# | |
upstream app-server { | |
ip_hash; | |
server localhost:9000; | |
# server localhost:9001; # used if clustering is available | |
} | |
# | |
# HTTPS | |
# | |
# server { | |
# listen 443 ssl; | |
# listen [::]:443 ssl; | |
# server_name my-host.com; | |
# | |
# ssl_certificate /etc/letsencrypt/live/my-host.com/fullchain.pem; | |
# ssl_certificate_key /etc/letsencrypt/live/my-host.com/privkey.pem; | |
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2; | |
# ssl_ciphers HIGH:!aNULL:!MD5; | |
# ssl_prefer_server_ciphers on; | |
# ssl_dhparam /etc/ssl/dhparams.pem; | |
# | |
# gzip on; | |
# gzip_proxied any; | |
# gzip_types | |
# text/css | |
# text/javascript | |
# text/xml | |
# text/plain | |
# image/svg+xml | |
# application/javascript | |
# application/x-javascript | |
# application/json; | |
# | |
# # Longer cache | |
# location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ { | |
# expires 6d; | |
# access_log off; | |
# add_header Cache-Control "public"; | |
# | |
# proxy_set_header X-Real-IP $remote_addr; | |
# proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
# proxy_set_header Host $http_host; | |
# proxy_set_header X-NginX-Proxy true; | |
# | |
# proxy_pass http://app-server; | |
# | |
# proxy_http_version 1.1; | |
# proxy_set_header Upgrade $http_upgrade; | |
# proxy_set_header Connection "upgrade"; | |
# | |
# error_page 502 = /502.html; | |
# error_page 501 503 504 505 = /505.html; | |
# } | |
# | |
# # Shorter cache | |
# location ~* \.(?:css|js)$ { | |
# expires 2d; | |
# access_log off; | |
# add_header Cache-Control "public"; | |
# | |
# proxy_set_header X-Real-IP $remote_addr; | |
# proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
# proxy_set_header Host $http_host; | |
# proxy_set_header X-NginX-Proxy true; | |
# | |
# proxy_pass http://app-server; | |
# | |
# proxy_http_version 1.1; | |
# proxy_set_header Upgrade $http_upgrade; | |
# proxy_set_header Connection "upgrade"; | |
# | |
# error_page 502 = /502.html; | |
# error_page 501 503 504 505 = /505.html; | |
# } | |
# | |
# location /api { | |
# expires 0s; | |
# | |
# proxy_set_header X-Real-IP $remote_addr; | |
# proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
# proxy_set_header Host $http_host; | |
# proxy_set_header X-NginX-Proxy true; | |
# proxy_pass http://app-server; | |
# proxy_http_version 1.1; | |
# | |
# proxy_set_header Upgrade $http_upgrade; | |
# proxy_set_header Connection "upgrade"; | |
# } | |
# | |
# location / { | |
# proxy_set_header X-Real-IP $remote_addr; | |
# proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
# proxy_set_header Host $http_host; | |
# proxy_set_header X-NginX-Proxy true; | |
# | |
# proxy_pass http://app-server; | |
# | |
# proxy_http_version 1.1; | |
# proxy_set_header Upgrade $http_upgrade; | |
# proxy_set_header Connection "upgrade"; | |
# | |
# error_page 502 = /502.html; | |
# error_page 501 503 504 505 = /505.html; | |
# } | |
# location /502.html { | |
# root /usr/share/nginx/html; | |
# } | |
# location /505.html { | |
# root /usr/share/nginx/html; | |
# } | |
# } | |
# HTTP | |
server { | |
listen 80; | |
listen [::]:80; | |
server_name my-host.com; | |
gzip on; | |
gzip_proxied any; | |
gzip_types | |
text/css | |
text/javascript | |
text/xml | |
text/plain | |
image/svg+xml | |
application/javascript | |
application/x-javascript | |
application/json; | |
# Longer cache | |
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ { | |
expires 6d; | |
access_log off; | |
add_header Cache-Control "public"; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-NginX-Proxy true; | |
proxy_pass http://app-server; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
error_page 502 = /502.html; | |
error_page 501 503 504 505 = /505.html; | |
} | |
# Shorter cache | |
location ~* \.(?:css|js)$ { | |
expires 3d; | |
access_log off; | |
add_header Cache-Control "public"; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-NginX-Proxy true; | |
proxy_pass http://app-server; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
error_page 502 = /502.html; | |
error_page 501 503 504 505 = /505.html; | |
} | |
location /api { | |
expires 0s; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-NginX-Proxy true; | |
proxy_pass http://app-server; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
} | |
location / { | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-NginX-Proxy true; | |
proxy_pass http://app-server; | |
proxy_http_version 1.1; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
error_page 502 = /502.html; | |
error_page 501 503 504 505 = /505.html; | |
# When HTTPS is ready: | |
# return 301 https://www.my-host.com$request_uri; | |
} | |
location /.well-known { | |
root /var/www/certbot; | |
} | |
location /502.html { | |
root /usr/share/nginx/html; | |
} | |
location /505.html { | |
root /usr/share/nginx/html; | |
} | |
} | |
EOF | |
# SERVICE UNAVAILABLE PAGE | |
sudo cat <<EOF > /usr/share/nginx/html/502.html | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Service unavailable</title> | |
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> | |
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> | |
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> | |
<style> | |
body { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMC8yOS8xMiKqq3kAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzVxteM2AAABHklEQVRIib2Vyw6EIAxFW5idr///Qx9sfG3pLEyJ3tAwi5EmBqRo7vHawiEEERHS6x7MTMxMVv6+z3tPMUYSkfTM/R0fEaG2bbMv+Gc4nZzn+dN4HAcREa3r+hi3bcuu68jLskhVIlW073tWaYlQ9+F9IpqmSfq+fwskhdO/AwmUTJXrOuaRQNeRkOd5lq7rXmS5InmERKoER/QMvUAPlZDHcZRhGN4CSeGY+aHMqgcks5RrHv/eeh455x5KrMq2yHQdibDO6ncG/KZWL7M8xDyS1/MIO0NJqdULLS81X6/X6aR0nqBSJcPeZnlZrzN477NKURn2Nus8sjzmEII0TfMiyxUuxphVWjpJkbx0btUnshRihVv70Bv8ItXq6Asoi/ZiCbU6YgAAAABJRU5ErkJggg==);} | |
.error-template {padding: 40px 15px;text-align: center;} | |
.error-actions {margin-top:15px;margin-bottom:15px;} | |
.error-actions .btn { margin-right:10px; } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-12"> | |
<div class="error-template"> | |
<h1>Ooops</h1> | |
<div class="error-details"> | |
The service you are trying to access is currently off line. | |
</div> | |
<div class="error-actions"> | |
<a href="http://www.tvrbo.pro" class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-home"></span> Take me Home</a> | |
<a href="mailto:[email protected]?subject=Unavailable" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-envelope"></span> Contact support</a> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> | |
EOF | |
# SERVER ERROR PAGE | |
sudo cat <<EOF > /usr/share/nginx/html/505.html | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Error</title> | |
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> | |
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> | |
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> | |
<style> | |
body { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMC8yOS8xMiKqq3kAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzVxteM2AAABHklEQVRIib2Vyw6EIAxFW5idr///Qx9sfG3pLEyJ3tAwi5EmBqRo7vHawiEEERHS6x7MTMxMVv6+z3tPMUYSkfTM/R0fEaG2bbMv+Gc4nZzn+dN4HAcREa3r+hi3bcuu68jLskhVIlW073tWaYlQ9+F9IpqmSfq+fwskhdO/AwmUTJXrOuaRQNeRkOd5lq7rXmS5InmERKoER/QMvUAPlZDHcZRhGN4CSeGY+aHMqgcks5RrHv/eeh455x5KrMq2yHQdibDO6ncG/KZWL7M8xDyS1/MIO0NJqdULLS81X6/X6aR0nqBSJcPeZnlZrzN477NKURn2Nus8sjzmEII0TfMiyxUuxphVWjpJkbx0btUnshRihVv70Bv8ItXq6Asoi/ZiCbU6YgAAAABJRU5ErkJggg==);} | |
.error-template {padding: 40px 15px;text-align: center;} | |
.error-actions {margin-top:15px;margin-bottom:15px;} | |
.error-actions .btn { margin-right:10px; } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-12"> | |
<div class="error-template"> | |
<h1>Ooops</h1> | |
<div class="error-details"> | |
The server has encountered an internal error and is unable to fulfill your request at this time. | |
</div> | |
<div class="error-actions"> | |
<a href="http://www.tvrbo.pro" class="btn btn-primary btn-lg"><span class="glyphicon glyphicon-home"></span> Take me Home</a> | |
<a href="mailto:[email protected]?subject=Error" class="btn btn-default btn-lg"><span class="glyphicon glyphicon-envelope"></span> Contact support</a> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> | |
EOF | |
sudo service nginx start | |
fi | |
# ------------------------------------------------------------------------- | |
# MONGODB | |
# ------------------------------------------------------------------------- | |
if [ $USE_MONGO ] | |
then | |
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 | |
echo "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/3.4 main" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list | |
sudo apt-get update | |
sudo apt-get install -y mongodb-org | |
sudo service mongod start | |
fi | |
# ------------------------------------------------------------------------- | |
# CERTBOT | |
# ------------------------------------------------------------------------- | |
if [ $USE_CERTBOT ] | |
then | |
sudo apt-get install -y certbot -t jessie-backports | |
sudo apt-get install -y python-certbot-nginx | |
# sudo certbot --nginx | |
# certbot --authenticator webroot --installer nginx --webroot-path /var/www/certbot | |
sudo cat <<'EOF' > /etc/cron.weekly/certbot-renew | |
#!/bin/bash | |
LOG=/root/certbot-renew.log | |
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | |
echo "-----------------------------------" >> $LOG | |
echo "STARTING CERTBOT RENEW" >> $LOG | |
date "+%Y/%m/%d %H:%M:%S" >> $LOG | |
if [ ! -x /usr/bin/certbot ] | |
then | |
echo "Unrunable script" >> $LOG | |
exit 1 | |
fi | |
/usr/bin/perl -e 'sleep int(rand(300))' | |
#/usr/bin/certbot -q renew >> $LOG | |
echo "RUNNING CERTBOT" >> $LOG | |
/usr/bin/certbot renew >> $LOG | |
if [ $? == 0 ] | |
then | |
echo "RELOADING NGINX" >> $LOG | |
/usr/sbin/service nginx reload >> $LOG | |
else | |
echo "CERTBOT ERROR - Will not reload Nginx" >> $LOG | |
fi | |
EOF | |
sudo chmod 755 /etc/cron.weekly/certbot-renew | |
sudo mkdir -p /var/www/certbot | |
fi | |
# ------------------------------------------------------------------------- | |
# BACKUPS | |
# ------------------------------------------------------------------------- | |
if [ $USE_BACKUP ] | |
then | |
echo "ADDING BACKUP FACILITIES" | |
mkdir /tmp/backup | |
cd /tmp/backup | |
sudo npm install gcloud-backup-toolset shelljs @google-cloud/storage bluebird | |
sudo cat <<'EOF' > /tmp/backup/backup.js | |
#!/usr/bin/env node | |
const config = require('./config.js'); | |
const lib = require('gcloud-backup-toolset'); | |
require('shelljs/global'); | |
var configuration = { | |
gCloudProjectId: config.gCloudProjectId, | |
gCloudKeyFilename: config.gCloudKeyFilename, | |
gCloudBucket: config.gCloudKeyFilename, | |
bucketSubdir: config.gCloudKeyFilename | |
}; | |
if(config.aesKey) | |
configuration.aesKey = config.aesKey; | |
function log(...args) { | |
console.log(new Date().toJSON(), "|", ...args, "\n"); | |
} | |
log("STARTING BACKUP", config.gCloudProjectId, config.backupName); | |
lib.doBackup(configuration, config.backupName, (tmpDir, report) => { | |
// copy files into tmpDir | |
// report is a report object you can use for logs and error | |
log(`The working folder is ${tmpDir}`); | |
cd(tmpDir); | |
log("DUMPING THE DATABASE"); | |
exec(`mongodump --db ${config.databaseName}`); | |
}) | |
.then((report)=>{ | |
log("BACKUP COMPLETE", config.gCloudProjectId, config.backupName); | |
log(report.toString()) | |
}) | |
.catch(err => { | |
log("BACKUP ERROR", err.message); | |
log(err); | |
}); | |
EOF | |
cat <<'EOF' > /tmp/backup/config.js | |
module.exports = { | |
gCloudProjectId: "my-app-id", | |
gCloudKeyFilename: __dirname + '/gcloud.json', | |
gCloudBucket: "my-app-backup", | |
bucketSubdir: "mongodb-backup", | |
//aesKey: "LOzKM6wlcd3NlSPjoEXfSbJimJXtwtLgGawTLjCpzHoTQMcHX4xN9YX97KRjNEO1", | |
databaseName: 'db-name', | |
backupName: 'weekly', | |
backupCopies: 5 | |
}; | |
EOF | |
cat <<'EOF' > /tmp/backup/rotate.js | |
#!/usr/bin/env node | |
const config = require('./config.js'); | |
const storage = require('@google-cloud/storage'); | |
const bluebird = require("bluebird"); | |
function log(...args) { | |
console.log(new Date().toJSON(), "|", ...args, "\n"); | |
} | |
var gcs = storage({ | |
projectId: config.gCloudProjectId, | |
keyFilename: config.gCloudKeyFilename | |
}); | |
log("STARTING ROTATION", config.gCloudProjectId, config.backupName); | |
const bucket = gcs.bucket(config.gCloudBucket); | |
// Remove old backups | |
listFiles(bucket, config.bucketSubdir).then(files => { | |
log(`GOT ${files.length} FILES`); | |
if(!files || files.length < config.backupCopies) return; | |
files = files.sort((file1, file2) => file2.metadata.timeCreated.localeCompare(file1.metadata.timeCreated)); | |
files = files.filter(file => parseInt(file.metadata.size)>0) | |
const cleanable = files.slice(config.backupCopies); | |
log(`CLEANING THE OLDEST ${cleanable.length}`); | |
return bluebird.map(cleanable, file => { | |
log('Cleaning', file.name); | |
return bucket.file(file.name).delete(); | |
}) | |
}) | |
.then(result => { | |
log("DONE", config.gCloudProjectId, config.backupName); | |
}) | |
.catch(err => { | |
log("ERROR: UNABLE TO ROTATE", err); | |
}); | |
// AUX | |
function listFiles(bucket, prefix) { | |
return new bluebird.Promise((resolve, reject) => { | |
var list = []; | |
function readResponse(err, files, nextQuery, apiResponse) { | |
if (err) return reject(err); | |
list = list.concat(files); | |
if (nextQuery) bucket.getFiles(nextQuery, readResponse); | |
else resolve(list); | |
} | |
bucket.getFiles({ | |
maxResults: 50, | |
prefix: prefix | |
}, readResponse); | |
}); | |
} | |
EOF | |
sudo mv /tmp/backup /root | |
cat <<'EOF' > /root/backup/TO-DO | |
1) Sign up on https://console.developers.google.com/apis?project=right-side-coffee | |
2) Create a project | |
3) Go to Credentials > Create Credentials > Service Account Key | |
4) Generate a JSON key file | |
5) Put it in this folder | |
6) Update the config.js file to match your environment | |
EOF | |
sudo cat <<'EOF' > /etc/cron.weekly/backup | |
#!/bin/bash | |
LOG=/root/backup/weekly.log | |
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | |
echo "-----------------------------------" >> $LOG | |
echo "STARTING WEEKLY BACKUP" >> $LOG | |
date "+%Y/%m/%d %H:%M:%S" >> $LOG | |
if [ ! -x /root/backup/backup.js ] | |
then | |
echo "Unrunable script" >> $LOG | |
exit 1 | |
fi | |
echo "RUNNING BACKUP" >> $LOG | |
/root/backup/backup.js >> $LOG 2>&1 | |
echo "RUNNING ROTATE" >> $LOG | |
/root/backup/rotate.js >> $LOG 2>&1 | |
echo "DONE" >> $LOG | |
EOF | |
# PERMISSIONS | |
sudo chmod 755 backup.js rotate.js /etc/cron.weekly/backup | |
fi | |
# ------------------------------------------------------------------------ | |
# OPTIONAL | |
# ------------------------------------------------------------------------- | |
#hostname my-host.com # set your domain | |
sudo apt-get install exim4 | |
sudo dpkg-reconfigure exim4-config | |
# set up | |
# https://www.digitalocean.com/community/tutorials/how-to-install-the-send-only-mail-server-exim-on-ubuntu-12-04 | |
# ------------------------------------------------------------------------ | |
# DONE | |
# ------------------------------------------------------------------------- | |
sudo reboot |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment