From 705d6eaf6af244997becff10cf12450a6b7d130b Mon Sep 17 00:00:00 2001 From: Attawit Kittikrairit Date: Sun, 5 Jul 2020 19:38:16 +0700 Subject: [PATCH] feat(nginx): add server deployment with automated NGINX and Let's Encrypt support --- examples/em-server-nginx/.example.env | 5 + examples/em-server-nginx/README.md | 57 +++++++++ .../docker-compose.prod-companion.yml | 13 +++ .../em-server-nginx/docker-compose.prod.yml | 109 ++++++++++++++++++ examples/em-server-nginx/webserver.conf | 16 +++ 5 files changed, 200 insertions(+) create mode 100644 examples/em-server-nginx/.example.env create mode 100644 examples/em-server-nginx/README.md create mode 100644 examples/em-server-nginx/docker-compose.prod-companion.yml create mode 100644 examples/em-server-nginx/docker-compose.prod.yml create mode 100644 examples/em-server-nginx/webserver.conf diff --git a/examples/em-server-nginx/.example.env b/examples/em-server-nginx/.example.env new file mode 100644 index 0000000..657d115 --- /dev/null +++ b/examples/em-server-nginx/.example.env @@ -0,0 +1,5 @@ +EM_DOMAIN=emission.mydomain.com +EM_LETSENCRYPT_EMAIL=your@email.com +EM_CLOUDFLARE_API_KEY=your-cloudflare-api-key +EM_CLOUDFLARE_ROOT_DOMAIN=mydomain.com +EM_CLOUDFLARE_SUBDOMAIN=emission diff --git a/examples/em-server-nginx/README.md b/examples/em-server-nginx/README.md new file mode 100644 index 0000000..4a23821 --- /dev/null +++ b/examples/em-server-nginx/README.md @@ -0,0 +1,57 @@ +# emission production deployment + +What will we deploy? + +1. mongodb +2. nginx-proxy (automated) +3. nginx-proxy-letsencrypt (automated) +4. emission-server +5. (optional) cloudflare-ddns client + +## Prerequisites + +1. A domain pointing to your server IP address. + In this example we will use `emission.mydomain.com` +2. Open port `80` and `443`. +3. `google_auth.json` at project root. +4. `seed_model.json` at project root. +5. `webserver.conf` at project root. + +## Configuration + +Configuration is done via `.env` file. First you need to create `.env` file. + +You can do this by executing: + +```bash +touch .env +``` + +Now let's put our configuration in the file like so: + +```bash +EM_DOMAIN=emission.mydomain.com +EM_LETSENCRYPT_EMAIL=your@email.com +``` + +## Deploying mandatory services + +```bash +source .env && docker-compose -f docker-compose.prod.yml up -d +``` + +## Deploying mandatory services and CloudFlare DDNS Client + +To deploy CloudFlare DDNS Client, you need to put additional configuration into `.env` file. + +Example configuration: + +```bash +EM_CLOUDFLARE_API_KEY=your-cloudflare-api-key +EM_CLOUDFLARE_ROOT_DOMAIN=mydomain.com +EM_CLOUDFLARE_SUBDOMAIN=emission +``` + +```bash +source .env && docker-compose -f docker-compose.prod.yml -f docker-compose.prod-companion.yml up -d +``` diff --git a/examples/em-server-nginx/docker-compose.prod-companion.yml b/examples/em-server-nginx/docker-compose.prod-companion.yml new file mode 100644 index 0000000..1441dda --- /dev/null +++ b/examples/em-server-nginx/docker-compose.prod-companion.yml @@ -0,0 +1,13 @@ +version: "3.7" +services: + cloudflare-ddns: + container_name: emddns + image: oznu/cloudflare-ddns + environment: + - API_KEY=${EM_CLOUDFLARE_API_KEY} + - ZONE=${EM_CLOUDFLARE_ROOT_DOMAIN} + - SUBDOMAIN=${EM_CLOUDFLARE_SUBDOMAIN} + - PROXIED=true + deploy: + restart_policy: + condition: always diff --git a/examples/em-server-nginx/docker-compose.prod.yml b/examples/em-server-nginx/docker-compose.prod.yml new file mode 100644 index 0000000..8ecf789 --- /dev/null +++ b/examples/em-server-nginx/docker-compose.prod.yml @@ -0,0 +1,109 @@ +version: "3.7" +services: + web-server: + container_name: ems + image: emission/e-mission-server:latest + depends_on: + - db + - nginx-proxy + - nginx-proxy-le + environment: + - DB_HOST=emdb + - WEB_SERVER_HOST=0.0.0.0 + # This tells nginx-proxy to map the specified domain to web-server service at port 8080 + # In this tempate the traffic from + # http://your.domain.name is proxied to http://web-server:8080 and + # https://your.domain.name is proxied to http://web-server:8080 + - VIRTUAL_HOST=${EM_DOMAIN} + - VIRTUAL_PORT=8080 + - LETSENCRYPT_HOST=${EM_DOMAIN} + deploy: + replicas: 1 + restart_policy: + condition: always + ports: + #This is a default port mapping. In production you might want to use 80:8080, + - "8081:8080" + volumes: + - tmp-data:/tmp + # You must place `google_auth.json` and `seed_model.json` at your current working directory + - ${PWD}/google_auth.json:/usr/src/app/conf/net/auth/google_auth.json:ro + - ${PWD}/seed_model.json:/usr/src/app/seed_model.json:ro + - ${PWD}/webserver.conf:/usr/src/app/conf/net/api/webserver.conf:ro + networks: + - emission + db: + container_name: emdb + image: mongo:latest + deploy: + restart_policy: + condition: always + ports: + # This port binding allows you to access the database server outside the host machine. Remove this is you don't need this + # functionality + - "27017:27017" + command: + mongod --bind_ip 0.0.0.0 + + # Volumes is the preferred way to persist data generated by a container. In this case we use a volume to persist the contents + # of the data base. Learn more about how to use volumes here: https://docs.docker.com/storage/volumes/ + # And learn how to configure volumes in your compose file here: https://docs.docker.com/compose/compose-file/#volume-configuration-reference + volumes: + - mongo-data:/data/db + networks: + - emission + # nginx-proxy automatically proxy http traffic to the service that has `VIRTUAL_HOST` environment variable defined at runtime + nginx-proxy: + container_name: emg + image: jwilder/nginx-proxy + labels: + - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy" + ports: + - "80:80" + - "443:443" + volumes: + - nginx_html:/usr/share/nginx + - nginx_certs:/etc/nginx/certs + - nginx_dhparam:/etc/nginx/dhparam + - nginx_vhostd:/etc/nginx/vhost.d + - /var/run/docker.sock:/tmp/docker.sock:ro + networks: + - emission + # nginx-proxy-le automatically retrieve necessary SSL certificate and private key for the specified domain defined + # with `LETSENCRYPT_HOST` environment variable. + nginx-proxy-le: + container_name: emg-le + image: jrcs/letsencrypt-nginx-proxy-companion + depends_on: + - nginx-proxy + volumes: + - nginx_html:/usr/share/nginx + - nginx_certs:/etc/nginx/certs + - nginx_dhparam:/etc/nginx/dhparam + - nginx_vhostd:/etc/nginx/vhost.d + - /var/run/docker.sock:/var/run/docker.sock:ro + environment: + # You MUST set your email address here (it is required by Let's Encrypt service) + - DEFAULT_EMAIL=${EM_LETSENCRYPT_EMAIL} + - NGINX_PROXY_CONTAINER=emg + networks: + - emission + +networks: + emission: + name: e-mission-server + +volumes: + tmp-data: + name: ems_tmp + mongo-data: + name: mongo-e-mission-server_data + nginx_html: + name: nginx_html + nginx_certs: + name: nginx_certs + nginx_dhparam: + name: nginx_dhparam + nginx_vhostd: + name: nginx_vhostd + diff --git a/examples/em-server-nginx/webserver.conf b/examples/em-server-nginx/webserver.conf new file mode 100644 index 0000000..b606c28 --- /dev/null +++ b/examples/em-server-nginx/webserver.conf @@ -0,0 +1,16 @@ +{ + "paths" : { + "static_path" : "webapp/www/", + "python_path" : "main", + "log_base_dir" : ".", + "log_file" : "debug.log" + }, + "__comment" : "Fill this in for the production server. port will almost certainly be 80 or 443. For iOS, using localhost allows you to test without an internet connection. For AWS and android, make sure that the host 0.0.0.0, localhost does not seem to work", + "server" : { + "host" : "0.0.0.0", + "port" : "8080", + "__comment": "1 hour = 60 min = 60 * 60 sec", + "timeout" : "3600", + "auth": "google_auth" + } +}