From 1c32c150f43e531a70deb0104996d44594b2e880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=98Addanus=E2=80=99?= Date: Sat, 10 Jul 2021 15:36:24 -0400 Subject: [PATCH] Added SSL how-to --- running-a-node.md | 1 + ssl-support/README.md | 88 ++++++++++++++++++++++++++ ssl-support/app.conf | 90 +++++++++++++++++++++++++++ ssl-support/docker-compose-sample.yml | 81 ++++++++++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 ssl-support/README.md create mode 100644 ssl-support/app.conf create mode 100644 ssl-support/docker-compose-sample.yml diff --git a/running-a-node.md b/running-a-node.md index 5e8920e..a215965 100644 --- a/running-a-node.md +++ b/running-a-node.md @@ -107,6 +107,7 @@ We recommend having a machine with at least 32GB of RAM and 50GB of storage. ### How do I configure SSL? There is an example SSL configuration in `nginx.dev`. + - here's one example of [Setting up SSL](ssl-support) ### How do I use the BlockCypher API? diff --git a/ssl-support/README.md b/ssl-support/README.md new file mode 100644 index 0000000..17d4861 --- /dev/null +++ b/ssl-support/README.md @@ -0,0 +1,88 @@ + +Setting up SSL within Docker for a Bitclout node/service - ex: running on GCP +I'm using cloutini.com as the sample domain - replace with your own. + +1. follow instructions to setup the Bitclout node. + - https://github.com/bitclout/run + - Ensure it runs in docker and is available on port 80. This will require enabling http (and https) firewall access, plus setting up an external IP address. That's out of scope (for now) + - http://cloutini.com/ + + +2. get letsencrypt... + + `cd bitclout/run/` + + `git clone https://github.com/wmnnd/nginx-certbot.git` + + `cd nginx-certbot` + + - note that the nginx-certbot folder might already be there from the bitclout node setup + + +3. edit this file + + `nano ./init-letsencrypt.sh` + + - add email address + + `email="cert@cloutini.com"` + + - replace all example.org except the last one in app.conf - place these domains in here using spaces - no commas + + `domains=(cloutini.com www.cloutini.com api.cloutini.com)` + + +4. find all files with example.org and replace with your domain + + `grep -r "example.org" ./` + + `nano ./data/nginx/app.conf` + + - keep the last `proxy_pass example.org` for now (proly) + + - see [app.conf](app.conf) + + +5. bring down nginx so that port 80 is available + + `docker stop nginx # or: docker-compose down` + + +6. use this to run a generic web server! + + ``` + # comment/replace this line in init-letsencrypt.sh + #docker-compose up --force-recreate -d nginx + + # replace it with this + docker stop web; docker run -it --rm -d -p 80:80 --name web -v $PWD/data/certbot/www/:/usr/share/nginx/html nginx; + ``` + + +7. run init-letsencrypt to add the multiple certs + + `./init-letsencrypt.sh # respond with y to replace if asked` + + +8. edit and replace the last example.org with http://frontend:8080; + + `nano ./data/nginx/app.conf` + + - the final file should look like [app.conf](app.conf) + + +9. Add the cert bot stuff to the main docker file for bitclout - see [docker-compose-sample.yml](docker-compose-sample.yml). + + `docker-compose build` + + `docker-compose down` + + `docker-compose up -d # can add the yml file using: -f docker-compose.dev.yml` + + +10. after bringing everything up again, check that the site is up - now on SSL + + - https://cloutini.com/ + + +Please submit a pull request or issue if anything above fails to work. diff --git a/ssl-support/app.conf b/ssl-support/app.conf new file mode 100644 index 0000000..4799b5e --- /dev/null +++ b/ssl-support/app.conf @@ -0,0 +1,90 @@ +map $http_origin $allow_origin +{ + # check the calling server. if we approve give its name to the browser + + # any cloutini subdomain is allowed to call us and give results to the user + ~^https?://(.*\.)?cloutini.com(:\d+)?$ $http_origin; + + # any bitclout subdomain is allowed to call us and give results to the user + ~^https?://(.*\.)?bitclout.com(:\d+)?$ $http_origin; + + # can add other supported domains here - like bitclout.com + + # NGINX won't set empty string headers, so if no match, header is unset. + # better yet - if no match, at least allow the main cloutini.com + default "https://cloutini.com"; +} + +server { + client_max_body_size 20m; + + listen 80; + server_name cloutini.com; + server_tokens off; + + # is a front end site (not api) + # other sites shouldn't refer to http:// anyway + # add_header 'Access-Control-Allow-Origin' '*'; + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + client_max_body_size 20m; + + listen 443 ssl; + server_name cloutini.com; + # server_tokens off; + + ssl_certificate /etc/letsencrypt/live/cloutini.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cloutini.com/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + location / { + add_header 'Access-Control-Allow-Origin' $allow_origin; + + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-NginX-Proxy true; + proxy_redirect off; + + # this might have been + # proxy_pass http://example.org; + + # will become this when all done + proxy_pass http://frontend:8080; + + } + + location /api/ { + # do not pass the CORS header from the response + # of the proxied server to the client... + # ignore value from node.js express caddyfile, etc + proxy_hide_header 'Access-Control-Allow-Origin'; + + + add_header 'Access-Control-Allow-Origin' $allow_origin; + + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-NginX-Proxy true; + proxy_redirect off; + + proxy_pass http://backend:17001; + + } +} + diff --git a/ssl-support/docker-compose-sample.yml b/ssl-support/docker-compose-sample.yml new file mode 100644 index 0000000..40075c6 --- /dev/null +++ b/ssl-support/docker-compose-sample.yml @@ -0,0 +1,81 @@ + + +backend: + container_name: backend + image: docker.io/bitclout/backend:latest + #to build local - will use ./backend/Dockerfile + #build: ./backend + command: run + volumes: + - db:/db + ports: + - 17001:17001 + - 17000:17000 + restart: always + env_file: + - bitclout_node.env + expose: + - "17001" + - "17000" + networks: + - cloutini_network + +frontend: + container_name: frontend + #image: docker.io/bitclout/frontend:stable + #to build local + build: ./frontend + ports: + - 8080:8080 + restart: always + volumes: + - ./:/app + env_file: + - bitclout_node.env + expose: + - "8080" + networks: + - cloutini_network + +nginx: + container_name: nginx + image: nginx:1.15-alpine + restart: always + volumes: + - ./nginx-certbot/data/nginx:/etc/nginx/conf.d + - ./nginx-certbot/data/certbot/conf:/etc/letsencrypt + - ./nginx-certbot/data/certbot/www:/var/www/certbot + ports: + - "80:80" + - "443:443" + command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'" + networks: + - cloutini_network + depends_on: + - backend + - frontend + +certbot: + container_name: certbot + image: certbot/certbot + restart: always + volumes: + - ./nginx-certbot/data/certbot/conf:/etc/letsencrypt + - ./nginx-certbot/data/certbot/www:/var/www/certbot + entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" + networks: + - cloutini_network + +# when don't specify external, docker creates a network +# ** we need(ed) an external network because +# the letsencrypt princess (was) in another castle (docker container) +# be sure to create this first using +# $ docker network create cloutini_network +networks: + cloutini_network: + driver: bridge + +# needed because using '- db:/db' under volumes above +volumes: + db: +