orchestration 0.3.8 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8569b93a7b22313b5633bb0d396a31c8a718f24eaa09f7968a8facd20a749934
4
- data.tar.gz: 14c9f928ebb9e19d4d5d437aa6e72c65d7c1cc3bfa56ff69ab42a81e23ce71c4
3
+ metadata.gz: 48a584dcfdfa1f9ef091d686a4ac83dac0fa56beea18a57fcd932e0e0afa4bab
4
+ data.tar.gz: 0fbb58d5067366eb986978285abc1f910c898f33eba18a7647a08455a583d226
5
5
  SHA512:
6
- metadata.gz: 9297540aa796b86d44bb62f4e34c94a44bc24463f66dd01d2f744e016eb0598085a80cf5393c7c4932293918db9e3f6110cfa6150eb989432c01d5cf907df72a
7
- data.tar.gz: affd54e64411b8f4f3be7096fc0525f25c50a1b46b4b3f01ae1588032cfe4c7e640fdc2c49890b1b63979da4fd3a8be5ed832af37760dbb5b774e0c28a994460
6
+ metadata.gz: 58e95bf102d2895a83eab7d14850a119492e17b427e81e05d373eeeda4459cabd1ed09038ba796140886399a750da2ef6bc7f2bf684ece9cca18a2e7f0a63219
7
+ data.tar.gz: 27d28ed0408efe5e88c323793b3feda57a5c29d9076aa6b28f78ee6da84e9fa609609e7e9cebee0e97ad309037b011434805b1b5670954eacda1031fb97bbeea
data/.gitignore CHANGED
@@ -25,3 +25,5 @@ spec/dummy/config/unicorn.rb
25
25
  orchestration-*.gem
26
26
 
27
27
  .byebug_history
28
+
29
+ TODO
data/README.md CHANGED
@@ -11,7 +11,7 @@ _Orchestration_ is a toolkit for testing, building, and deploying _Ruby_ (includ
11
11
  Add _Orchestration_ to your Gemfile:
12
12
 
13
13
  ```ruby
14
- gem 'orchestration', '~> 0.3.8'
14
+ gem 'orchestration', '~> 0.3.9'
15
15
  ```
16
16
 
17
17
  Install:
@@ -18,9 +18,9 @@ en:
18
18
  ready: "Mongo is ready."
19
19
  bad_config: "Unable to parse Mongo config: %{path}. Expected section for one of: %{expected}"
20
20
 
21
- nginx_proxy:
22
- waiting: "Waiting for Nginx proxy: %{config}"
23
- ready: "Nginx proxy is ready."
21
+ haproxy:
22
+ waiting: "Waiting for HAProxy: %{config}"
23
+ ready: "HAProxy is ready."
24
24
 
25
25
  rabbitmq:
26
26
  waiting: "Waiting for RabbitMQ: %{config}"
@@ -53,8 +53,8 @@ en:
53
53
  mongo:
54
54
  wait: "Wait for Mongo to become available"
55
55
 
56
- nginx_proxy:
57
- wait: "Wait for Nginx proxy to become available"
56
+ haproxy:
57
+ wait: "Wait for HAProxy to become available"
58
58
 
59
59
  rabbitmq:
60
60
  wait: "Wait for RabbitMQ to become available"
@@ -11,11 +11,7 @@ module Orchestration
11
11
  def definition
12
12
  {
13
13
  'image' => '${DOCKER_ORGANIZATION}/${DOCKER_REPOSITORY}',
14
- 'environment' => environment,
15
- 'expose' => [8080],
16
- 'volumes' => [
17
- "#{@config.env.public_volume}:/app/public/:ro"
18
- ]
14
+ 'environment' => environment
19
15
  }
20
16
  end
21
17
 
@@ -23,17 +19,18 @@ module Orchestration
23
19
 
24
20
  def environment
25
21
  {
26
- 'DATABASE_URL' => @config.database_url,
27
22
  'RAILS_LOG_TO_STDOUT' => '1',
23
+ 'RAILS_SERVE_STATIC_FILES' => '1',
28
24
  'UNICORN_PRELOAD_APP' => '1',
29
25
  'UNICORN_TIMEOUT' => '60',
30
26
  'UNICORN_WORKER_PROCESSES' => '8',
31
- 'VIRTUAL_PORT' => '8080'
27
+ 'SERVICE_PORTS' => '8080'
32
28
  }.merge(inherited_environment)
33
29
  end
34
30
 
35
31
  def inherited_environment
36
32
  {
33
+ 'DATABASE_URL' => nil,
37
34
  'HOST_UID' => nil,
38
35
  'RAILS_ENV' => nil,
39
36
  'SECRET_KEY_BASE' => nil,
@@ -18,7 +18,7 @@ module Orchestration
18
18
  end
19
19
 
20
20
  def volumes
21
- public_volume.merge(database_volume).merge(mongo_volume)
21
+ {}.merge(database_volume).merge(mongo_volume)
22
22
  end
23
23
 
24
24
  private
@@ -29,7 +29,7 @@ module Orchestration
29
29
  database: DatabaseService,
30
30
  mongo: MongoService,
31
31
  rabbitmq: RabbitMQService,
32
- nginx_proxy: NginxProxyService
32
+ haproxy: HAProxyService
33
33
  }
34
34
  end
35
35
 
@@ -42,10 +42,6 @@ module Orchestration
42
42
  end.compact
43
43
  end
44
44
 
45
- def public_volume
46
- { @env.public_volume => {} }
47
- end
48
-
49
45
  def database_volume
50
46
  return {} unless services.key?('database')
51
47
 
@@ -35,7 +35,7 @@ module Orchestration
35
35
  end
36
36
 
37
37
  def volumes
38
- return {} if @environment == :test
38
+ return {} unless @environment == :development
39
39
 
40
40
  { 'volumes' => ["#{volume}:#{@config.adapter.data_dir}"] }
41
41
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Orchestration
4
4
  module DockerCompose
5
- class NginxProxyService
5
+ class HAProxyService
6
6
  def initialize(config, environment)
7
7
  @environment = environment
8
8
  @config = config
@@ -10,11 +10,13 @@ module Orchestration
10
10
 
11
11
  def definition
12
12
  {
13
- 'image' => 'rubyorchestration/nginx-proxy',
13
+ 'deploy' => {
14
+ 'placement' => { 'constraints' => ['node.role == manager'] }
15
+ },
16
+ 'image' => 'dockercloud/haproxy',
14
17
  'ports' => %w[${LISTEN_PORT}:80],
15
18
  'volumes' => [
16
- '/var/run/docker.sock:/tmp/docker.sock:ro',
17
- "#{@config.env.public_volume}:/var/www/public/:ro"
19
+ '/var/run/docker.sock:/var/run/docker.sock:ro'
18
20
  ]
19
21
  }
20
22
  end
@@ -53,7 +53,7 @@ module Orchestration
53
53
  {
54
54
  'version' => compose_config(environment).version,
55
55
  'services' => services(environment)
56
- }.merge('volumes' => volumes(environment))
56
+ }
57
57
  end
58
58
 
59
59
  def services(environment)
@@ -79,7 +79,7 @@ module Orchestration
79
79
  when :test, :development
80
80
  %i[database mongo rabbitmq]
81
81
  when :production
82
- %i[nginx_proxy app database mongo rabbitmq]
82
+ %i[haproxy app database mongo rabbitmq]
83
83
  when nil
84
84
  []
85
85
  else
@@ -99,7 +99,7 @@ module Orchestration
99
99
  database: Orchestration::Services::Database::Configuration,
100
100
  mongo: Orchestration::Services::Mongo::Configuration,
101
101
  rabbitmq: Orchestration::Services::RabbitMQ::Configuration,
102
- nginx_proxy: Orchestration::Services::NginxProxy::Configuration
102
+ haproxy: Orchestration::Services::HAProxy::Configuration
103
103
  }.fetch(service).new(@env)
104
104
  end
105
105
 
@@ -11,5 +11,5 @@ require 'orchestration/docker_compose/configuration'
11
11
  require 'orchestration/docker_compose/app_service'
12
12
  require 'orchestration/docker_compose/database_service'
13
13
  require 'orchestration/docker_compose/mongo_service'
14
- require 'orchestration/docker_compose/nginx_proxy_service'
14
+ require 'orchestration/docker_compose/haproxy_service'
15
15
  require 'orchestration/docker_compose/rabbitmq_service'
@@ -32,9 +32,9 @@ module Orchestration
32
32
  end
33
33
 
34
34
  def local_port
35
- key = @service_name == 'app' ? 'nginx_proxy' : @service_name
35
+ key = @service_name == 'app' ? 'haproxy' : @service_name
36
36
 
37
- return ENV.fetch('LISTEN_PORT', '3000').to_i if key == 'nginx_proxy'
37
+ return ENV.fetch('LISTEN_PORT', '3000').to_i if key == 'haproxy'
38
38
 
39
39
  @env.docker_compose_config
40
40
  .fetch('services')
@@ -2,11 +2,11 @@
2
2
 
3
3
  module Orchestration
4
4
  module Services
5
- module NginxProxy
5
+ module HAProxy
6
6
  class Configuration
7
7
  include ConfigurationBase
8
8
 
9
- self.service_name = 'nginx_proxy'
9
+ self.service_name = 'haproxy'
10
10
 
11
11
  def initialize(env, service_name = nil)
12
12
  super
@@ -14,7 +14,7 @@ module Orchestration
14
14
  end
15
15
 
16
16
  def friendly_config
17
- "[nginx_proxy] #{host}:#{local_port}"
17
+ "[haproxy] #{host}:#{local_port}"
18
18
  end
19
19
  end
20
20
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Orchestration
4
4
  module Services
5
- module NginxProxy
5
+ module HAProxy
6
6
  class Healthcheck
7
7
  include HealthcheckBase
8
8
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Orchestration
4
+ module Services
5
+ module HAProxy
6
+ end
7
+ end
8
+ end
9
+
10
+ require 'orchestration/services/haproxy/configuration'
11
+ require 'orchestration/services/haproxy/healthcheck'
@@ -12,5 +12,5 @@ require 'orchestration/services/app'
12
12
  require 'orchestration/services/database'
13
13
  require 'orchestration/services/listener'
14
14
  require 'orchestration/services/mongo'
15
- require 'orchestration/services/nginx_proxy'
15
+ require 'orchestration/services/haproxy'
16
16
  require 'orchestration/services/rabbitmq'
@@ -9,40 +9,45 @@ endif
9
9
 
10
10
  verify-environment:
11
11
  ifndef VIRTUAL_HOST
12
- @$(error `VIRTUAL_HOST` must be defined in environment)
12
+ @$(error `VIRTUAL_HOST` must be defined in environment)
13
13
  endif
14
14
 
15
15
  ifndef LISTEN_PORT
16
- @$(error `LISTEN_PORT` must be defined in environment)
16
+ @$(error `LISTEN_PORT` must be defined in environment)
17
17
  endif
18
18
 
19
19
  ifndef env
20
- @$(error Either `env`, `RACK_ENV` or `RAILS_ENV` must be defined in environment)
20
+ @$(error Either `env`, `RACK_ENV` or `RAILS_ENV` must be defined in environment)
21
21
  endif
22
22
 
23
+ project_name:=%%REPOSITORY%%_${env}
23
24
  compose_base:=env HOST_UID=$(shell id -u) \
24
25
  DOCKER_ORGANIZATION=%%ORGANIZATION%% \
25
26
  DOCKER_REPOSITORY=%%REPOSITORY%%:%%VERSION%% \
26
27
  docker-compose \
27
- -p %%REPOSITORY%%_${env} \
28
+ -p ${project_name} \
28
29
  -f docker-compose.yml
29
30
 
30
31
  compose:=${compose_base} -f docker-compose.production.yml -f docker-compose.override.yml
31
32
 
32
33
  .PHONY: deploy
33
34
  deploy:
34
- @echo "Deploying application to Docker swarm..."
35
- @${compose} config | docker stack deploy -c - %%REPOSITORY%%_${env}
35
+ ifndef manager
36
+ @$(error Missing `manager` parameter: `make deploy manager=swarm-manager.example.com`)
37
+ else
38
+ @tar -cf - . | ssh ${manager} 'cd $$(mktemp -d) ; chmod 0700 . ; cat - | tar -x ; make deploy-stack ; rm -r $$(pwd)'
39
+ endif
36
40
 
37
- .PHONY: stop
38
- stop:
39
- @echo "Stopping containers..."
40
- @${compose} down
41
+ .PHONY: deploy-stack
42
+ deploy-stack:
43
+ @${compose} config | docker stack deploy --prune --with-registry-auth -c - ${project_name}
41
44
 
42
- .PHONY: start
43
- start:
44
- @echo "Launching application..."
45
- @${compose} up -d --scale app=$${instances:-1}
45
+ .PHONY: console
46
+ service := app
47
+ command := /bin/bash
48
+ console:
49
+ @echo "Creating temporary container..."
50
+ @${compose} run --rm ${service} ${command}
46
51
 
47
52
  .PHONY: config
48
53
  config:
@@ -53,8 +58,13 @@ pull:
53
58
  @${compose} pull
54
59
 
55
60
  .PHONY: logs
61
+ service := app
56
62
  logs:
57
- @${compose} logs -f
63
+ ifndef manager
64
+ @$(error Missing `manager` parameter: `make logs manager=swarm-manager.example.com`)
65
+ else
66
+ ssh ${manager} "docker service logs -f ${project_name}_${service}"
67
+ endif
58
68
 
59
69
  .PHONY: migrate
60
70
  migrate:
@@ -1,6 +1,5 @@
1
- # Set VIRTUAL_HOST to whatever host(s) your application will be available on.
2
- # See https://github.com/jwilder/nginx-proxy for more details on this variable.
3
- VIRTUAL_HOST=localhost
4
-
5
- # Set the port your application will be available on (via Nginx proxy)
1
+ # Your application will be available on this port when deployed to the Swarm:
6
2
  LISTEN_PORT=3000
3
+
4
+ # Comma-separated list of hostnames your application will be available on:
5
+ VIRTUAL_HOST=localhost
@@ -5,11 +5,13 @@ SHELL:=/bin/bash
5
5
  -include .env
6
6
  export
7
7
 
8
- ifneq (,$(RAILS_ENV))
8
+ ifneq (,$(env))
9
+ env:=$(env)
10
+ else ifneq (,$(RAILS_ENV))
9
11
  env:=$(RAILS_ENV)
10
12
  else ifneq (,$(RACK_ENV))
11
13
  env:=$(RACK_ENV)
12
- else ifeq (,$(env))
14
+ else
13
15
  env:=development
14
16
  endif
15
17
 
@@ -92,13 +94,15 @@ bundle:
92
94
  .PHONY: migrate
93
95
  migrate:
94
96
  @echo "Running migrations..."
95
- ifeq (${env},$(filter ${env},test development))
96
97
  @(${rake} db:create && ${rake} db:migrate) || ${rake} db:migrate
97
- else
98
- @${compose} run --rm app bin/rake db:migrate RAILS_ENV=${env}
99
- endif
100
98
  @echo "Migrations complete."
101
99
 
100
+ .PHONY: migrate-container
101
+ migrate-container:
102
+ @echo "[app] Running migrations..."
103
+ @${compose} run --rm app make migrate env=${env}
104
+ @echo "[app] Migrations complete."
105
+
102
106
  ### Service healthcheck commands ###
103
107
 
104
108
  .PHONY: wait
@@ -132,10 +136,10 @@ endif
132
136
 
133
137
  ## Production wait commands
134
138
 
135
- .PHONY: wait-nginx_proxy
136
- wait-nginx_proxy:
139
+ .PHONY: wait-haproxy
140
+ wait-haproxy:
137
141
  ifneq (${env},$(filter ${env},test development))
138
- @${rake} orchestration:nginx_proxy:wait LISTEN_PORT=${LISTEN_PORT}
142
+ @${rake} orchestration:haproxy:wait LISTEN_PORT=${LISTEN_PORT}
139
143
  endif
140
144
 
141
145
  .PHONY: wait-app
@@ -22,6 +22,7 @@ module Orchestration
22
22
  def write(desc, message, color_name = nil, newline = true)
23
23
  output = newline ? "#{message}\n" : message.to_s
24
24
  STDOUT.print colorize(desc, output, color_name)
25
+ STDOUT.flush
25
26
  end
26
27
 
27
28
  def read(message, default = nil)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Orchestration
4
- VERSION = '0.3.8'
4
+ VERSION = '0.3.9'
5
5
  end
@@ -29,10 +29,10 @@ namespace :orchestration do
29
29
  end
30
30
  end
31
31
 
32
- namespace :nginx_proxy do
33
- desc I18n.t('orchestration.rake.nginx_proxy.wait')
32
+ namespace :haproxy do
33
+ desc I18n.t('orchestration.rake.haproxy.wait')
34
34
  task :wait do
35
- Orchestration::Services::NginxProxy::Healthcheck.start
35
+ Orchestration::Services::HAProxy::Healthcheck.start
36
36
  end
37
37
  end
38
38
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orchestration
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Farrell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-17 00:00:00.000000000 Z
11
+ date: 2019-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -325,7 +325,6 @@ files:
325
325
  - Makefile
326
326
  - README.md
327
327
  - Rakefile
328
- - TODO
329
328
  - bin/console
330
329
  - bin/rspec
331
330
  - bin/rubocop
@@ -338,9 +337,9 @@ files:
338
337
  - lib/orchestration/docker_compose/app_service.rb
339
338
  - lib/orchestration/docker_compose/configuration.rb
340
339
  - lib/orchestration/docker_compose/database_service.rb
340
+ - lib/orchestration/docker_compose/haproxy_service.rb
341
341
  - lib/orchestration/docker_compose/install_generator.rb
342
342
  - lib/orchestration/docker_compose/mongo_service.rb
343
- - lib/orchestration/docker_compose/nginx_proxy_service.rb
344
343
  - lib/orchestration/docker_compose/rabbitmq_service.rb
345
344
  - lib/orchestration/environment.rb
346
345
  - lib/orchestration/errors.rb
@@ -360,6 +359,9 @@ files:
360
359
  - lib/orchestration/services/database/adapters/sqlite3.rb
361
360
  - lib/orchestration/services/database/configuration.rb
362
361
  - lib/orchestration/services/database/healthcheck.rb
362
+ - lib/orchestration/services/haproxy.rb
363
+ - lib/orchestration/services/haproxy/configuration.rb
364
+ - lib/orchestration/services/haproxy/healthcheck.rb
363
365
  - lib/orchestration/services/healthcheck_base.rb
364
366
  - lib/orchestration/services/listener.rb
365
367
  - lib/orchestration/services/listener/configuration.rb
@@ -367,9 +369,6 @@ files:
367
369
  - lib/orchestration/services/mongo.rb
368
370
  - lib/orchestration/services/mongo/configuration.rb
369
371
  - lib/orchestration/services/mongo/healthcheck.rb
370
- - lib/orchestration/services/nginx_proxy.rb
371
- - lib/orchestration/services/nginx_proxy/configuration.rb
372
- - lib/orchestration/services/nginx_proxy/healthcheck.rb
373
372
  - lib/orchestration/services/rabbitmq.rb
374
373
  - lib/orchestration/services/rabbitmq/configuration.rb
375
374
  - lib/orchestration/services/rabbitmq/healthcheck.rb
@@ -380,7 +379,6 @@ files:
380
379
  - lib/orchestration/templates/docker-compose.override.yml.erb
381
380
  - lib/orchestration/templates/entrypoint.sh.erb
382
381
  - lib/orchestration/templates/env.erb
383
- - lib/orchestration/templates/nginx.tmpl.erb
384
382
  - lib/orchestration/templates/orchestration.mk.erb
385
383
  - lib/orchestration/templates/unicorn.rb.erb
386
384
  - lib/orchestration/templates/yaml.bash.erb
data/TODO DELETED
@@ -1,24 +0,0 @@
1
- Refactor docker-compose services - these really belong in
2
- lib/orchestration/services/<service-name>/docker_compose.rb
3
-
4
- Add default logging section to each service ?
5
-
6
- Redis support
7
-
8
- Use `Paint` instead of `Colorize` for colouring output - better licensing and no
9
- monkeypatching `String` etc.
10
-
11
- Make unicorn `config.rb` resilient to database connectivity failures
12
-
13
- Group healthcheck rake tasks - run all at once in the same process. Create a
14
- master process that generates config files and calls each healthcheck in batch.
15
-
16
- Provide a way of declaratively configuring bespoke healthchecks.
17
-
18
- Auto-healthcheck any services with a local port bind using the Listener
19
- healthcheck.
20
-
21
- Add remote Docker swarm management.
22
- https://github.com/mikejmoore/docker-swarm-sdk
23
-
24
- Add scp and ssh execution of docker-compose bundle to servers.
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Orchestration
4
- module Services
5
- module NginxProxy
6
- end
7
- end
8
- end
9
-
10
- require 'orchestration/services/nginx_proxy/configuration'
11
- require 'orchestration/services/nginx_proxy/healthcheck'
@@ -1,364 +0,0 @@
1
- {{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }}
2
-
3
- {{ define "upstream" }}
4
- {{ if .Address }}
5
- {{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
6
- {{ if and .Container.Node.ID .Address.HostPort }}
7
- # {{ .Container.Node.Name }}/{{ .Container.Name }}
8
- server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }};
9
- {{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}}
10
- {{ else if .Network }}
11
- # {{ .Container.Name }}
12
- server {{ .Network.IP }}:{{ .Address.Port }};
13
- {{ end }}
14
- {{ else if .Network }}
15
- # {{ .Container.Name }}
16
- {{ if .Network.IP }}
17
- server {{ .Network.IP }} down;
18
- {{ else }}
19
- server 127.0.0.1 down;
20
- {{ end }}
21
- {{ end }}
22
-
23
- {{ end }}
24
-
25
- # If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
26
- # scheme used to connect to this server
27
- map $http_x_forwarded_proto $proxy_x_forwarded_proto {
28
- default $http_x_forwarded_proto;
29
- '' $scheme;
30
- }
31
-
32
- # If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
33
- # server port the client connected to
34
- map $http_x_forwarded_port $proxy_x_forwarded_port {
35
- default $http_x_forwarded_port;
36
- '' $server_port;
37
- }
38
-
39
- # If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
40
- # Connection header that may have been passed to this server
41
- map $http_upgrade $proxy_connection {
42
- default upgrade;
43
- '' close;
44
- }
45
-
46
- # Apply fix for very long server names
47
- server_names_hash_bucket_size 128;
48
-
49
- # Default dhparam
50
- {{ if (exists "/etc/nginx/dhparam/dhparam.pem") }}
51
- ssl_dhparam /etc/nginx/dhparam/dhparam.pem;
52
- {{ end }}
53
-
54
- # Set appropriate X-Forwarded-Ssl header
55
- map $scheme $proxy_x_forwarded_ssl {
56
- default off;
57
- https on;
58
- }
59
-
60
- gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
61
-
62
- log_format vhost '$host $remote_addr - $remote_user [$time_local] '
63
- '"$request" $status $body_bytes_sent '
64
- '"$http_referer" "$http_user_agent"';
65
-
66
- access_log off;
67
-
68
- {{ if $.Env.RESOLVERS }}
69
- resolver {{ $.Env.RESOLVERS }};
70
- {{ end }}
71
-
72
- {{ if (exists "/etc/nginx/proxy.conf") }}
73
- include /etc/nginx/proxy.conf;
74
- {{ else }}
75
- # HTTP 1.1 support
76
- proxy_http_version 1.1;
77
- proxy_buffering off;
78
- proxy_set_header Host $http_host;
79
- proxy_set_header Upgrade $http_upgrade;
80
- proxy_set_header Connection $proxy_connection;
81
- proxy_set_header X-Real-IP $remote_addr;
82
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
83
- proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
84
- proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
85
- proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
86
-
87
- # Mitigate httpoxy attack (see README for details)
88
- proxy_set_header Proxy "";
89
- {{ end }}
90
-
91
- {{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }}
92
- server {
93
- server_name _; # This is just an invalid value which will never trigger on a real hostname.
94
- listen 80;
95
- {{ if $enable_ipv6 }}
96
- listen [::]:80;
97
- {{ end }}
98
- access_log /var/log/nginx/access.log vhost;
99
- return 503;
100
- }
101
-
102
- {{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
103
- server {
104
- server_name _; # This is just an invalid value which will never trigger on a real hostname.
105
- listen 443 ssl http2;
106
- {{ if $enable_ipv6 }}
107
- listen [::]:443 ssl http2;
108
- {{ end }}
109
- access_log /var/log/nginx/access.log vhost;
110
- return 503;
111
-
112
- ssl_session_tickets off;
113
- ssl_certificate /etc/nginx/certs/default.crt;
114
- ssl_certificate_key /etc/nginx/certs/default.key;
115
- }
116
- {{ end }}
117
-
118
- {{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
119
-
120
- {{ $host := trim $host }}
121
- {{ $is_regexp := hasPrefix "~" $host }}
122
- {{ $upstream_name := when $is_regexp (sha1 $host) $host }}
123
-
124
- # {{ $host }}
125
- upstream {{ $upstream_name }} {
126
-
127
- {{ range $container := $containers }}
128
- {{ $addrLen := len $container.Addresses }}
129
-
130
- {{ range $knownNetwork := $CurrentContainer.Networks }}
131
- {{ range $containerNetwork := $container.Networks }}
132
- {{ if (and (ne $containerNetwork.Name "ingress") (or (eq $knownNetwork.Name $containerNetwork.Name) (eq $knownNetwork.Name "host"))) }}
133
- ## Can be connected with "{{ $containerNetwork.Name }}" network
134
-
135
- {{/* If only 1 port exposed, use that */}}
136
- {{ if eq $addrLen 1 }}
137
- {{ $address := index $container.Addresses 0 }}
138
- {{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
139
- {{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
140
- {{ else }}
141
- {{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
142
- {{ $address := where $container.Addresses "Port" $port | first }}
143
- {{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
144
- {{ end }}
145
- {{ else }}
146
- # Cannot connect to network of this container
147
- server 127.0.0.1 down;
148
- {{ end }}
149
- {{ end }}
150
- {{ end }}
151
- {{ end }}
152
- }
153
-
154
- {{ $default_host := or ($.Env.DEFAULT_HOST) "" }}
155
- {{ $default_server := index (dict $host "" $default_host "default_server") $host }}
156
-
157
- {{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}}
158
- {{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }}
159
-
160
- {{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}}
161
- {{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }}
162
-
163
- {{/* Get the HTTPS_METHOD defined by containers w/ the same vhost, falling back to "redirect" */}}
164
- {{ $https_method := or (first (groupByKeys $containers "Env.HTTPS_METHOD")) "redirect" }}
165
-
166
- {{/* Get the SSL_POLICY defined by containers w/ the same vhost, falling back to "Mozilla-Intermediate" */}}
167
- {{ $ssl_policy := or (first (groupByKeys $containers "Env.SSL_POLICY")) "Mozilla-Intermediate" }}
168
-
169
- {{/* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000" */}}
170
- {{ $hsts := or (first (groupByKeys $containers "Env.HSTS")) "max-age=31536000" }}
171
-
172
- {{/* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}}
173
- {{ $vhost_root := or (first (groupByKeys $containers "Env.VIRTUAL_ROOT")) "/var/www/public" }}
174
-
175
-
176
- {{/* Get the first cert name defined by containers w/ the same vhost */}}
177
- {{ $certName := (first (groupByKeys $containers "Env.CERT_NAME")) }}
178
-
179
- {{/* Get the best matching cert by name for the vhost. */}}
180
- {{ $vhostCert := (closest (dir "/etc/nginx/certs") (printf "%s.crt" $host))}}
181
-
182
- {{/* vhostCert is actually a filename so remove any suffixes since they are added later */}}
183
- {{ $vhostCert := trimSuffix ".crt" $vhostCert }}
184
- {{ $vhostCert := trimSuffix ".key" $vhostCert }}
185
-
186
- {{/* Use the cert specified on the container or fallback to the best vhost match */}}
187
- {{ $cert := (coalesce $certName $vhostCert) }}
188
-
189
- {{ $is_https := (and (ne $https_method "nohttps") (ne $cert "") (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert))) }}
190
-
191
- {{ if $is_https }}
192
-
193
- {{ if eq $https_method "redirect" }}
194
- server {
195
- server_name {{ $host }};
196
- listen 80 {{ $default_server }};
197
- {{ if $enable_ipv6 }}
198
- listen [::]:80 {{ $default_server }};
199
- {{ end }}
200
- access_log /var/log/nginx/access.log vhost;
201
- return 301 https://$host$request_uri;
202
- }
203
- {{ end }}
204
-
205
- server {
206
- server_name {{ $host }};
207
- listen 443 ssl http2 {{ $default_server }};
208
- {{ if $enable_ipv6 }}
209
- listen [::]:443 ssl http2 {{ $default_server }};
210
- {{ end }}
211
- access_log /var/log/nginx/access.log vhost;
212
-
213
- {{ if eq $network_tag "internal" }}
214
- # Only allow traffic from internal clients
215
- include /etc/nginx/network_internal.conf;
216
- {{ end }}
217
-
218
- {{ if eq $ssl_policy "Mozilla-Modern" }}
219
- ssl_protocols TLSv1.2 TLSv1.3;
220
- ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
221
- {{ else if eq $ssl_policy "Mozilla-Intermediate" }}
222
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
223
- ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS';
224
- {{ else if eq $ssl_policy "Mozilla-Old" }}
225
- ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
226
- ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP';
227
- {{ else if eq $ssl_policy "AWS-TLS-1-2-2017-01" }}
228
- ssl_protocols TLSv1.2 TLSv1.3;
229
- ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES128-SHA256:AES256-GCM-SHA384:AES256-SHA256';
230
- {{ else if eq $ssl_policy "AWS-TLS-1-1-2017-01" }}
231
- ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
232
- ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
233
- {{ else if eq $ssl_policy "AWS-2016-08" }}
234
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
235
- ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
236
- {{ else if eq $ssl_policy "AWS-2015-05" }}
237
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
238
- ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DES-CBC3-SHA';
239
- {{ else if eq $ssl_policy "AWS-2015-03" }}
240
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
241
- ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA';
242
- {{ else if eq $ssl_policy "AWS-2015-02" }}
243
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
244
- ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA';
245
- {{ end }}
246
-
247
- ssl_prefer_server_ciphers on;
248
- ssl_session_timeout 5m;
249
- ssl_session_cache shared:SSL:50m;
250
- ssl_session_tickets off;
251
-
252
- ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $cert) }};
253
- ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $cert) }};
254
-
255
- {{ if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $cert)) }}
256
- ssl_dhparam {{ printf "/etc/nginx/certs/%s.dhparam.pem" $cert }};
257
- {{ end }}
258
-
259
- {{ if (exists (printf "/etc/nginx/certs/%s.chain.pem" $cert)) }}
260
- ssl_stapling on;
261
- ssl_stapling_verify on;
262
- ssl_trusted_certificate {{ printf "/etc/nginx/certs/%s.chain.pem" $cert }};
263
- {{ end }}
264
-
265
- {{ if (and (ne $https_method "noredirect") (ne $hsts "off")) }}
266
- add_header Strict-Transport-Security "{{ trim $hsts }}" always;
267
- {{ end }}
268
-
269
- {{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
270
- include {{ printf "/etc/nginx/vhost.d/%s" $host }};
271
- {{ else if (exists "/etc/nginx/vhost.d/default") }}
272
- include /etc/nginx/vhost.d/default;
273
- {{ end }}
274
-
275
- root /var/www/public;
276
- try_files $uri @application;
277
-
278
- location @application {
279
- {{ if eq $proto "uwsgi" }}
280
- include uwsgi_params;
281
- uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
282
- {{ else if eq $proto "fastcgi" }}
283
- root {{ trim $vhost_root }};
284
- include fastcgi.conf;
285
- fastcgi_pass {{ trim $upstream_name }};
286
- {{ else }}
287
- proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
288
- {{ end }}
289
-
290
- {{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
291
- auth_basic "Restricted {{ $host }}";
292
- auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
293
- {{ end }}
294
- {{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
295
- include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
296
- {{ else if (exists "/etc/nginx/vhost.d/default_location") }}
297
- include /etc/nginx/vhost.d/default_location;
298
- {{ end }}
299
- }
300
- }
301
-
302
- {{ end }}
303
-
304
- {{ if or (not $is_https) (eq $https_method "noredirect") }}
305
-
306
- server {
307
- server_name {{ $host }};
308
- listen 80 {{ $default_server }};
309
- {{ if $enable_ipv6 }}
310
- listen [::]:80 {{ $default_server }};
311
- {{ end }}
312
- access_log /var/log/nginx/access.log vhost;
313
-
314
- {{ if eq $network_tag "internal" }}
315
- # Only allow traffic from internal clients
316
- include /etc/nginx/network_internal.conf;
317
- {{ end }}
318
-
319
- {{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
320
- include {{ printf "/etc/nginx/vhost.d/%s" $host }};
321
- {{ else if (exists "/etc/nginx/vhost.d/default") }}
322
- include /etc/nginx/vhost.d/default;
323
- {{ end }}
324
-
325
- root /var/www/public;
326
- try_files $uri @application;
327
-
328
- location @application {
329
- {{ if eq $proto "uwsgi" }}
330
- include uwsgi_params;
331
- uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
332
- {{ else if eq $proto "fastcgi" }}
333
- root {{ trim $vhost_root }};
334
- include fastcgi.conf;
335
- fastcgi_pass {{ trim $upstream_name }};
336
- {{ else }}
337
- proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
338
- {{ end }}
339
-
340
- {{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
341
- include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
342
- {{ else if (exists "/etc/nginx/vhost.d/default_location") }}
343
- include /etc/nginx/vhost.d/default_location;
344
- {{ end }}
345
- }
346
- }
347
-
348
- {{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
349
- server {
350
- server_name {{ $host }};
351
- listen 443 ssl http2 {{ $default_server }};
352
- {{ if $enable_ipv6 }}
353
- listen [::]:443 ssl http2 {{ $default_server }};
354
- {{ end }}
355
- access_log /var/log/nginx/access.log vhost;
356
- return 500;
357
-
358
- ssl_certificate /etc/nginx/certs/default.crt;
359
- ssl_certificate_key /etc/nginx/certs/default.key;
360
- }
361
- {{ end }}
362
-
363
- {{ end }}
364
- {{ end }}