Lets Encrypt support

pull/332/head
Piero Toffanin 2017-11-17 13:42:34 -05:00
rodzic c7cb95f386
commit b46ae07b5a
11 zmienionych plików z 292 dodań i 27 usunięć

4
.env
Wyświetl plik

@ -1,3 +1,7 @@
HOST=localhost
PORT=8000
MEDIA_DIR=appmedia
SSL=NO
SSL_KEY=
SSL_CERT=
SSL_INSECURE_PORT_REDIRECT=80

1
.gitignore vendored
Wyświetl plik

@ -94,3 +94,4 @@ webpack-stats.json
pip-selfcheck.json
.idea/
package-lock.json
.cronenv

Wyświetl plik

@ -8,17 +8,7 @@ ENV PYTHONPATH $PYTHONPATH:/webodm
RUN mkdir /webodm
WORKDIR /webodm
# Install pip reqs
ADD requirements.txt /webodm/
RUN pip install -r requirements.txt
ADD . /webodm/
RUN git submodule update --init
# Install Node.js
RUN curl --silent --location https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get install -y nodejs
# Configure use of testing branch of Debian
RUN printf "Package: *\nPin: release a=stable\nPin-Priority: 900\n" > /etc/apt/preferences.d/stable.pref
@ -26,8 +16,19 @@ RUN printf "Package: *\nPin: release a=testing\nPin-Priority: 750\n" > /etc/apt/
RUN printf "deb http://mirror.steadfast.net/debian/ stable main contrib non-free\ndeb-src http://mirror.steadfast.net/debian/ stable main contrib non-free" > /etc/apt/sources.list.d/stable.list
RUN printf "deb http://mirror.steadfast.net/debian/ testing main contrib non-free\ndeb-src http://mirror.steadfast.net/debian/ testing main contrib non-free" > /etc/apt/sources.list.d/testing.list
# Install GDAL, nginx
RUN apt-get update && apt-get install -t testing -y binutils libproj-dev gdal-bin nginx gettext-base
# Install Node.js GDAL, nginx, letsencrypt
RUN apt-get update && apt-get install -t testing -y binutils libproj-dev gdal-bin nginx && apt-get install nodejs gettext-base cron certbot
# Install pip reqs
ADD requirements.txt /webodm/
RUN pip install -r requirements.txt
ADD . /webodm/
# Setup cron
RUN ln -s /webodm/nginx/crontab /etc/cron.d/nginx-cron && chmod 0644 /webodm/nginx/crontab && service cron start
RUN git submodule update --init
WORKDIR /webodm/nodeodm/external/node-OpenDroneMap
RUN npm install

Wyświetl plik

@ -0,0 +1,7 @@
# This configuration adds the volumes necessary for SSL manual setup
version: '2'
services:
webapp:
volumes:
- ${SSL_KEY}:/webodm/nginx/ssl/key.pem
- ${SSL_CERT}:/webodm/nginx/ssl/cert.pem

Wyświetl plik

@ -0,0 +1,14 @@
# This configuration adds support for SSL
version: '2'
volumes:
letsencrypt:
driver: local
services:
webapp:
ports:
- "${SSL_INSECURE_PORT_REDIRECT}:8080"
volumes:
- letsencrypt:/webodm/nginx/letsencrypt
environment:
- SSL
- SSL_KEY

1
nginx/.gitignore vendored
Wyświetl plik

@ -1,2 +1,3 @@
ssl/
letsencrypt/
*.conf

4
nginx/crontab 100644
Wyświetl plik

@ -0,0 +1,4 @@
# Automatically renew the SSL certificate (if needed)
0 0 1 * * root source /webodm/.cronenv; bash -c "/webodm/nginx/letsencrypt-autogen.sh"
# An empty line is required at the end of this file for a valid cron file.

Wyświetl plik

@ -0,0 +1,43 @@
#!/bin/bash
set -eo pipefail
__dirname=$(cd $(dirname "$0"); pwd -P)
cd ${__dirname}
hash certbot 2>/dev/null || not_found=true
if [ $not_found ]; then
echo "Certbot not found. You need to install certbot to use this script."
exit 1
fi
if [ "$SSL" = "NO" ] || [ ! -z "$SSL_KEY" ]; then
echo "SSL not enabled, or manual SSL key specified, exiting."
exit 1
fi
DOMAIN="${HOST:=$1}"
if [ -z $DOMAIN ]; then
echo "Usage: $0 <my.domain.com>"
exit 1
fi
# Generate/update certificate
certbot certonly --work-dir ./letsencrypt --config-dir ./letsencrypt --logs-dir ./letsencrypt --standalone -d $DOMAIN --register-unsafely-without-email --agree-tos --keep
# Create ssl dir if necessary
if [ ! -e ssl/ ]; then
mkdir ssl
fi
# Update symlinks
if [ -e ssl/key.pem ]; then
rm ssl/key.pem
fi
if [ -e ssl/cert.pem ]; then
rm ssl/cert.pem
fi
if [ -e "letsencrypt/live/$DOMAIN" ]; then
ln -vs "letsencrypt/live/$DOMAIN/privkey.pem" ssl/key.pem
ln -vs "letsencrypt/live/$DOMAIN/chain.pem" ssl/cert.pem
fi

Wyświetl plik

@ -0,0 +1,88 @@
worker_processes 1;
# Change this if running outside docker!
user root root;
pid /tmp/nginx.pid;
error_log /tmp/nginx.error.log;
events {
worker_connections 1024; # increase if you have lots of clients
accept_mutex off; # set to 'on' if nginx worker_processes > 1
use epoll;
}
http {
include /etc/nginx/mime.types;
# fallback in case we can't determine a type
default_type application/octet-stream;
access_log /tmp/nginx.access.log combined;
sendfile on;
upstream app_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response
# for UNIX domain socket setups
server unix:/tmp/gunicorn.sock fail_timeout=0;
}
# Redirect all non-encrypted to encrypted
server {
server_name $HOST;
listen 8080;
return 301 https://$HOST:$PORT$request_uri;
}
server {
listen 8000 deferred;
client_max_body_size 0;
server_name $HOST;
ssl on;
ssl_certificate /webodm/nginx/ssl/cert.pem
ssl_certificate_key /webodm/nginx/ssl/key.pem
keepalive_timeout 5;
proxy_connect_timeout 360s;
proxy_read_timeout 360s;
# path for static files
location /static {
root /webodm/build;
}
# path for certain media files that don't need permissions enforced
location /media/CACHE {
root /webodm/app;
}
location /media/settings {
autoindex on;
root /webodm/app;
}
location / {
# CORS settings
# These settings are VERY permissive, consider tightening them
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
proxy_pass http://app_server;
}
}
}

Wyświetl plik

@ -61,6 +61,9 @@ fi
export HOST="${HOST:=localhost}"
export PORT="${PORT:=8000}"
# Dump environment to .cronenv
printenv > .cronenv
(sleep 5; echo
echo -e "\033[92m"
echo "Congratulations! └@(・◡・)@┐"
@ -86,7 +89,19 @@ else
envsubst '\$HOST \$OTHER_VAR' < $templ > ${templ%.*}
done
nginx -c $(pwd)/nginx/nginx.conf
# Check if we need to auto-generate SSL certs via letsencrypt
if [ "$SSL" = "YES" ] && [ -z "$SSL_KEY" ]; then
bash -c "nginx/letsencrypt-autogen.sh"
fi
# Check if SSL key/certs are available
conf="nginx.conf"
if [ -e nginx/ssl ];
echo "Using nginx SSL configuration"
conf="nginx-ssl.conf"
fi
nginx -c $(pwd)/nginx/$conf
gunicorn webodm.wsgi --bind unix:/tmp/gunicorn.sock --timeout 360 --preload
fi

115
webodm.sh
Wyświetl plik

@ -1,5 +1,7 @@
#!/bin/bash
set -eo pipefail
__dirname=$(cd $(dirname "$0"); pwd -P)
cd ${__dirname}
platform="Linux" # Assumed
uname=$(uname)
@ -16,25 +18,86 @@ if [[ $platform = "Windows" ]]; then
export COMPOSE_CONVERT_WINDOWS_PATHS=1
fi
# Set default env variables
export PORT="${WEBODM_PORT:=8000}"
export HOST="${WEBODM_HOST:=localhost}"
export MEDIA_DIR="${WEBODM_MEDIA_DIR:=appmedia}"
# Load default values
source .env
DEFAULT_PORT="$PORT"
DEFAULT_HOST="$HOST"
DEFAULT_MEDIA_DIR="$MEDIA_DIR"
DEFAULT_SSL="$SSL"
DEFAULT_SSL_INSECURE_PORT_REDIRECT="$SSL_INSECURE_PORT_REDIRECT"
# Parse args for overrides
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
--port)
export PORT="$2"
shift # past argument
shift # past value
;;
--hostname)
export HOST="$2"
shift # past argument
shift # past value
;;
--media-dir)
export MEDIA_DIR=$(realpath "$2")
shift # past argument
shift # past value
;;
--ssl)
SSL=YES
shift # past argument
;;
--ssl-key)
export SSL_KEY=$(realpath "$2")
shift # past argument
shift # past value
;;
--ssl-cert)
export SSL_CERT=$(realpath "$2")
shift # past argument
shift # past value
;;
--ssl-insecure-port-redirect)
export SSL_INSECURE_PORT_REDIRECT="$2"
shift # past argument
shift # past value
;;
*) # unknown option
POSITIONAL+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameter
usage(){
echo "Usage: $0 <command> [options]"
echo "Usage: $0 <command>"
echo
echo "This program helps to manage the setup/teardown of the docker containers for running WebODM. We recommend that you read the full documentation of docker at https://docs.docker.com if you want to customize your setup."
echo
echo "Command list:"
echo " start Start WebODM"
echo " stop Stop WebODM"
echo " down Stop and remove WebODM's docker containers"
echo " update Update WebODM to the latest release"
echo " rebuild Rebuild all docker containers and perform cleanups"
echo " checkenv Do an environment check and install missing components"
echo " test Run the unit test suite (developers only)"
echo " start [options] Start WebODM"
echo " stop Stop WebODM"
echo " down Stop and remove WebODM's docker containers"
echo " update Update WebODM to the latest release"
echo " rebuild Rebuild all docker containers and perform cleanups"
echo " checkenv Do an environment check and install missing components"
echo " test Run the unit test suite (developers only)"
echo " resetadminpassword <newpassword> Reset the administrator's password to a new one. WebODM must be running when executing this command."
echo ""
echo "Options:"
echo " --port <port> Set the port that WebODM should bind to (default: $DEFAULT_PORT)"
echo " --hostname <hostname> Set the hostname that WebODM will be accessible from (default: $DEFAULT_HOST)"
echo " --media-dir <path> Path where processing results will be stored to (default: $DEFAULT_MEDIA_DIR (docker named volume))"
echo " --ssl Enable SSL and automatically request and install a certificate from letsencrypt.org. (default: $DEFAULT_SSL)"
echo " --ssl-key <path> Manually specify a path to the private key file (.pem) to use with nginx to enable SSL (default: None)"
echo " --ssl-cert <path> Manually specify a path to the certificate file (.pem) to use with nginx to enable SSL (default: None)"
echo " --ssl-insecure-port-redirect <port> Insecure port number to redirect from when SSL is enabled (default: $DEFAULT_SSL_INSECURE_PORT_REDIRECT)"
exit
}
@ -79,6 +142,26 @@ run(){
start(){
command="docker-compose -f docker-compose.yml -f docker-compose.nodeodm.yml"
if [ "$SSL" = "YES" ]; then
if [ ! -z "$SSL_KEY" ] && [ ! -e "$SSL_KEY" ]; then
echo -e "\033[91mSSL key file does not exist: $SSL_KEY\033[39m"
exit 1
fi
if [ ! -z "$SSL_CERT" ] && [ ! -e "$SSL_CERT" ]; then
echo -e "\033[91mSSL certificate file does not exist: $SSL_CERT\033[39m"
exit 1
fi
command+=" -f docker-compose.ssl.yml"
method="Lets Encrypt"
if [ ! -z "$SSL_KEY" ] && [ ! -z "$SSL_CERT" ]; then
method="Manual"
command+=" -f docker-compose.ssl-manual.yml"
fi
echo "SSL will be enabled ($method)"
fi
run "$command start || $command up"
}
@ -128,11 +211,15 @@ if [[ $1 = "start" ]]; then
echo "Starting WebODM..."
echo ""
echo "Using the following environment:"
echo "============"
echo "================================"
echo "Host: $HOST"
echo "Port: $PORT"
echo "Media directory: $MEDIA_DIR"
echo "============"
echo "SSL: $SSL"
echo "SSL key: $SSL_KEY"
echo "SSL certificate: $SSL_CERT"
echo "SSL insecure port redirect: $SSL_INSECURE_PORT_REDIRECT"
echo "================================"
echo "Make sure to issue a $0 down if you decide to change the environment."
echo ""