SequenceDiagram/docs/ubuntu-nginx-installer.sh

380 lines
9.7 KiB
Bash

# This script was used to build sequence.davidje13.com
# It will install the sequence diagram code (and necessary environment)
# and install an nginx proxy server. It will also use the "let's encrypt"
# service to get SSH keys for the site.
# Security updates will be applied automatically. Other updates can be
# applied by running:
# sudo apt-get update;
# sudo apt-get dist-upgrade;
# sudo shutdown -r now; # if needed
# sudo apt-get autoremove;
# The github code can be updated by running:
# sudo /var/www/sequence/update.sh
# The AWS configuration used:
# EC2:
# Community AMI: ami-0b91bd72, T2.micro, 8GB (only uses ~2GB but this is the minimum)
# Use a security group which allows 80 (public), 443 (public) and 22 (your ip)
# (assign elastic IP)
# Route53:
# A <domain> <elastic ip> (1day)
# A www.<domain> <elastic ip> (1day)
# A sequence.<domain> <elastic ip> (1day)
# CAA <domain> 0 issue "letsencrypt.org" (1day)
# Once the EC2 & Route53 config is done, log in to the box and run this script.
# Pass a single parameter: the main domain name (e.g. davidje13.com)
# You can easily download this script to the box by running:
# wget https://davidje13.github.io/SequenceDiagram/docs/ubuntu-nginx-installer.sh;
# chmod 0744 ubuntu-nginx-installer.sh;
# ./ubuntu-nginx-installer.sh
# thanks,
# https://gist.github.com/nrollr/9a39bb636a820fb97eec2ed85e473d38
# https://bjornjohansen.no/redirect-to-https-with-nginx
# http://tumblr.intranation.com/post/766288369/using-nginx-reverse-proxy
# https://certbot.eff.org/
# https://help.ubuntu.com/lts/serverguide/automatic-updates.html
# https://cloud-images.ubuntu.com/locator/ec2/
# https://gist.github.com/alonisser/a2c19f5362c2091ac1e7
# https://www.freedesktop.org/software/systemd/man/systemd.service.html
set -ex
DOMAIN="$1";
if [[ -z "$DOMAIN" ]]; then
echo "Must specify domain!";
exit 1;
fi;
echo 'iptables-persistent iptables-persistent/autosave_v4 boolean true' | sudo debconf-set-selections;
echo 'iptables-persistent iptables-persistent/autosave_v6 boolean true' | sudo debconf-set-selections;
sudo tee -a /etc/apt/apt.conf.d/20auto-upgrades <<'EOF' > /dev/null;
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
EOF
sudo tee -a /etc/apt/apt.conf.d/50unattended-upgrades <<'EOF' > /dev/null;
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
EOF
sudo add-apt-repository ppa:certbot/certbot -y;
sudo apt-get update;
sudo apt-get dist-upgrade -y;
sudo apt-get install -y \
iptables-persistent \
daemontools \
certbot \
nodejs \
npm \
nginx;
sudo systemctl stop nginx;
sudo useradd --system --user-group --password '' sequence-runner;
sudo mkdir -p /var/www/http/.well-known/acme-challenge;
sudo mkdir -p /var/www/https;
git clone https://github.com/davidje13/SequenceDiagram.git;
cd SequenceDiagram && npm install --production; cd - > /dev/null;
sudo mv SequenceDiagram /var/www/sequence;
sudo mkdir -p /var/www/sequence/logs;
sudo tee /var/www/sequence/runner.sh <<'EOF' > /dev/null;
#!/bin/bash
BASEDIR="$(dirname "$0")";
PORT="$1";
mkdir -p "$BASEDIR/logs/log$PORT";
FONTDIR="$BASEDIR/fonts" \
"$BASEDIR/bin/server.js" "$PORT" 2>&1 \
> >(multilog n50 s1048576 "$BASEDIR/logs/log$PORT") &
echo $! > "$BASEDIR/logs/pid$PORT";
EOF
sudo tee /var/www/sequence/update.sh <<'EOF' > /dev/null;
#!/bin/bash
BASEDIR="$(dirname "$0")";
cd "$BASEDIR";
git fetch;
if (( "$(git rev-list HEAD..origin/master --count)" > 0 )); then
git pull;
chmod -R g-w .;
systemctl restart sequence8080.service;
systemctl restart sequence8081.service;
fi;
cd - > /dev/null;
EOF
sudo tee /var/www/https/index.htm <<EOF > /dev/null;
<!DOCTYPE html>
<html lang="en">
<head>
<title>$DOMAIN</title>
<style>
body {
font: 1em sans-serif;
color: #444444;
text-align: center;
padding: 50px 20px 20px;
margin: 0;
}
a:link, a:visited {
color: #4466AA;
text-decoration: underline;
}
a:active, a:hover {
color: #6699BB;
text-decoration: none;
}
</style>
</head>
<body>
Nothing to see here&hellip;
try <a href="https://sequence.$DOMAIN/">https://sequence.$DOMAIN/</a> instead for now.
</body>
</html>
EOF
sudo chmod 0544 /var/www/sequence/runner.sh;
sudo chmod 0744 /var/www/sequence/update.sh;
sudo chmod -R g-w /var/www/sequence;
sudo chown -R root:sequence-runner /var/www/sequence;
sudo chown -R sequence-runner:sequence-runner /var/www/sequence/logs;
sudo chown sequence-runner:sequence-runner /var/www/sequence/runner.sh;
sudo chown -R root:www-data /var/www/http;
sudo chown -R root:www-data /var/www/https;
openssl dhparam -out dhparam.pem 2048;
sudo mv dhparam.pem /etc/nginx/dhparam.pem;
sudo chmod 0600 /etc/nginx/dhparam.pem;
sudo chown root:root /etc/nginx/dhparam.pem;
sudo rm /etc/nginx/modules-enabled/50-mod-http-geoip.conf;
sudo rm /etc/nginx/modules-enabled/50-mod-http-image-filter.conf;
sudo rm /etc/nginx/modules-enabled/50-mod-http-xslt-filter.conf;
sudo rm /etc/nginx/modules-enabled/50-mod-mail.conf;
# should be mod-stream remaining
sudo rm /etc/nginx/sites-enabled/default;
sudo tee /etc/nginx/nginx.conf <<EOF > /dev/null;
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
EOF
sudo tee /etc/nginx/conf.d/custom.conf <<EOF > /dev/null;
server_tokens off;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
EOF
sudo tee /etc/nginx/conf.d/mime.conf <<EOF > /dev/null;
types {
application/javascript mjs;
}
EOF
sudo tee /etc/nginx/sites-available/shared-ssl.inc <<EOF > /dev/null;
ssl on;
ssl_session_cache shared:SSL:5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_certificate /etc/letsencrypt/live/all/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/all/privkey.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/all/fullchain.pem;
EOF
sudo tee /etc/nginx/sites-available/http <<EOF > /dev/null;
server {
listen 8000 default_server;
listen [::]:8000 default_server;
root /var/www/http;
keepalive_requests 1;
keepalive_timeout 0s;
client_header_timeout 5s;
client_body_timeout 5s;
client_max_body_size 1;
location / {
access_log off;
expires max;
return 301 https://\$host\$request_uri;
}
location /.well-known/acme-challenge/ {
}
}
EOF
sudo tee /etc/nginx/sites-available/root <<EOF > /dev/null;
server {
server_name $DOMAIN www.$DOMAIN;
listen 8443 ssl http2;
listen [::]:8443 ssl http2;
# listen 8000
# listen [::]:8000
root /var/www/https;
include /etc/nginx/sites-available/shared-ssl.inc;
index index.htm index.html;
client_header_timeout 5s;
client_body_timeout 5s;
client_max_body_size 1;
gzip on;
gzip_comp_level 4;
gzip_types *;
location /errors/ {
internal;
}
error_page 404 /errors/404.htm;
}
EOF
sudo tee /etc/nginx/sites-available/sequence <<EOF > /dev/null;
upstream sequence_backend {
server 127.0.0.1:8080 max_conns=64;
server 127.0.0.1:8081 max_conns=64;
keepalive 16;
}
server {
server_name sequence.$DOMAIN;
listen 8443 ssl http2;
listen [::]:8443 ssl http2;
# listen 8000
# listen [::]:8000
include /etc/nginx/sites-available/shared-ssl.inc;
client_header_timeout 5s;
client_body_timeout 5s;
client_max_body_size 1;
access_log off;
error_log off;
merge_slashes off;
location / {
proxy_pass http://sequence_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_redirect off;
proxy_buffering off;
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/http /etc/nginx/sites-enabled/http;
sudo systemctl start nginx;
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8000;
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443;
sudo ip6tables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8000;
sudo ip6tables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443;
sudo certbot certonly --agree-tos --register-unsafely-without-email --cert-name all --webroot \
-w /var/www/http \
-d "$DOMAIN" \
-d "www.$DOMAIN" \
-d "sequence.$DOMAIN";
make_sequence_service() {
PORT="$1";
sudo tee "/lib/systemd/system/sequence$PORT.service" <<EOF > /dev/null;
[Unit]
Description=Sequence Diagram Server $PORT
After=network.target
[Service]
Type=forking
PIDFile=/var/www/sequence/logs/pid$PORT
User=sequence-runner
ExecStart=/var/www/sequence/runner.sh $PORT
KillMode=process
KillSignal=SIGINT
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo chmod 0644 "/lib/systemd/system/sequence$PORT.service";
sudo systemctl enable "sequence$PORT.service";
}
make_sequence_service 8080;
make_sequence_service 8081;
sudo systemctl start sequence8080.service;
sudo systemctl start sequence8081.service;
sudo ln -s /etc/nginx/sites-available/root /etc/nginx/sites-enabled/root;
sudo ln -s /etc/nginx/sites-available/sequence /etc/nginx/sites-enabled/sequence;
sudo nginx -s reload;
sudo iptables-save | sudo tee /etc/iptables/rules.v4 > /dev/null;
sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 > /dev/null;
sudo tee /etc/cron.daily/sequence-pull <<'EOF' > /dev/null;
#!/bin/sh
/var/www/sequence/update.sh;
EOF
sudo chmod 0755 /etc/cron.daily/sequence-pull;
sudo rm /etc/cron.d/certbot;
sudo tee /etc/cron.daily/certbot-renew <<'EOF' > /dev/null;
#!/bin/sh
certbot renew -q --deploy-hook "nginx -s reload";
EOF
sudo chmod 0755 /etc/cron.daily/certbot-renew;