Skip to content

Instantly share code, notes, and snippets.

@brickpop
Last active May 23, 2018 18:41
Show Gist options
  • Save brickpop/01f4229f3506ea5bd5f02c1dcafce880 to your computer and use it in GitHub Desktop.
Save brickpop/01f4229f3506ea5bd5f02c1dcafce880 to your computer and use it in GitHub Desktop.
Debian Jessie Server setup
#!/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
#!/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