potluck-nginx 0.0.1
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 +7 -0
 - data/LICENSE +16 -0
 - data/README.md +31 -0
 - data/lib/potluck/nginx.rb +255 -0
 - data/lib/potluck/nginx/ssl.rb +110 -0
 - data/lib/potluck/nginx/util.rb +27 -0
 - metadata +99 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 599537fcab6df50b0126d73460295be4b366101667ad4c2317199b361153a5c1
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 6a38b16b915efa971b1b93361dd1b995937b67a61031376879cf0aae857438be
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: f007969613094559c4b68707b8bf87f570def7da9b5122673de84ca2a4c45409450ba348f7d8ff522191188afacdf1cf1a94c15f1a0b4cc36419e446ca921644
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 6c3672941908c91d9151e7863ed0cb93c7e7ebf4463bcc2b7c8d997ac3baf529ef124bad4a1733c33ee3221a12cfad0cd41c60f72f85f9f2c1921f4d2646a436
         
     | 
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright 2021 Nate Pickens
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
         
     | 
| 
      
 4 
     | 
    
         
            +
            documentation files (the "Software"), to deal in the Software without restriction, including without
         
     | 
| 
      
 5 
     | 
    
         
            +
            limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
         
     | 
| 
      
 6 
     | 
    
         
            +
            the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
         
     | 
| 
      
 7 
     | 
    
         
            +
            conditions:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all copies or substantial
         
     | 
| 
      
 10 
     | 
    
         
            +
            portions of the Software.
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
         
     | 
| 
      
 13 
     | 
    
         
            +
            LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
         
     | 
| 
      
 14 
     | 
    
         
            +
            EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
         
     | 
| 
      
 15 
     | 
    
         
            +
            AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
         
     | 
| 
      
 16 
     | 
    
         
            +
            OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Potluck - Nginx
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            An extension to the Potluck gem that provides control over the Nginx process and its configuration files
         
     | 
| 
      
 4 
     | 
    
         
            +
            from Ruby.
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Add this line to your Gemfile:
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 11 
     | 
    
         
            +
            gem('potluck-nginx')
         
     | 
| 
      
 12 
     | 
    
         
            +
            ```
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            Or install manually on the command line:
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 17 
     | 
    
         
            +
            gem install potluck-nginx
         
     | 
| 
      
 18 
     | 
    
         
            +
            ```
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            [Coming soon.]
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            Bug reports and pull requests are welcome on GitHub at https://github.com/npickens/potluck.
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            ## License
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            The gem is available as open source under the terms of the
         
     | 
| 
      
 31 
     | 
    
         
            +
            [MIT License](https://opensource.org/licenses/MIT).
         
     | 
| 
         @@ -0,0 +1,255 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require('fileutils')
         
     | 
| 
      
 4 
     | 
    
         
            +
            require('potluck')
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative('nginx/ssl')
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative('nginx/util')
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Potluck
         
     | 
| 
      
 9 
     | 
    
         
            +
              class Nginx < Dish
         
     | 
| 
      
 10 
     | 
    
         
            +
                CONFIG_NAME_ACTIVE = 'nginx.conf'
         
     | 
| 
      
 11 
     | 
    
         
            +
                CONFIG_NAME_INACTIVE = 'nginx-stopped.conf'
         
     | 
| 
      
 12 
     | 
    
         
            +
                ACTIVE_CONFIG_PATTERN = File.join(DIR, '*', CONFIG_NAME_ACTIVE).freeze
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                TEST_CONFIG_REGEX = /nginx: configuration file (?<config>.+) test (failed|is successful)/.freeze
         
     | 
| 
      
 15 
     | 
    
         
            +
                INCLUDE_REGEX = /^ *include +#{Regexp.escape(ACTIVE_CONFIG_PATTERN)} *;/.freeze
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def initialize(hosts, port, subdomains: nil, ssl: nil, one_host: false, www: nil, multiple_slashes: nil,
         
     | 
| 
      
 18 
     | 
    
         
            +
                    multiple_question_marks: nil, trailing_slash: nil, trailing_question_mark: nil, config: {}, **args)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  super(**args)
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  @hosts = Array(hosts).map { |h| h.sub(/^www\./, '') }.uniq
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @hosts += @hosts.map { |h| "www.#{h}" }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @host = @hosts.first
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @port = port
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  @dir = File.join(DIR, @host)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @ssl = SSL.new(self, @dir, @host, **ssl) if ssl
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  @scheme = @ssl ? 'https' : 'http'
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @other_scheme = @ssl ? 'http' : 'https'
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @one_host = !!one_host
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @subdomains = Array(subdomains)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @www = www
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @multiple_slashes = multiple_slashes
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @multiple_question_marks = multiple_question_marks
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @trailing_slash = trailing_slash
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @trailing_question_mark = trailing_question_mark
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @additional_config = config
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  FileUtils.mkdir_p(DIR)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  FileUtils.mkdir_p(@dir)
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  @config_file_active = File.join(@dir, CONFIG_NAME_ACTIVE).freeze
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @config_file_inactive = File.join(@dir, CONFIG_NAME_INACTIVE).freeze
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def start
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @ssl&.ensure_files
         
     | 
| 
      
 49 
     | 
    
         
            +
                  ensure_host_entries
         
     | 
| 
      
 50 
     | 
    
         
            +
                  ensure_include
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  write_config
         
     | 
| 
      
 53 
     | 
    
         
            +
                  activate_config
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  run('nginx -t')
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  status == :active ? reload : super
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def stop(hard = false)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  deactivate_config
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  hard || status != :active ? super() : reload
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def reload
         
     | 
| 
      
 67 
     | 
    
         
            +
                  run('nginx -s reload')
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                private
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def config
         
     | 
| 
      
 73 
     | 
    
         
            +
                  host_subdomains_regex = ([@host] + @subdomains).join('|')
         
     | 
| 
      
 74 
     | 
    
         
            +
                  hosts_subdomains_regex = (@hosts + @subdomains).join('|')
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  config = {
         
     | 
| 
      
 77 
     | 
    
         
            +
                    "upstream #{@host}" => {
         
     | 
| 
      
 78 
     | 
    
         
            +
                      'server' => "127.0.0.1:#{@port}",
         
     | 
| 
      
 79 
     | 
    
         
            +
                    },
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                    'server' => Util.deep_merge!({
         
     | 
| 
      
 82 
     | 
    
         
            +
                      'charset' => 'UTF-8',
         
     | 
| 
      
 83 
     | 
    
         
            +
                      'access_log' => File.join(@dir, 'nginx-access.log'),
         
     | 
| 
      
 84 
     | 
    
         
            +
                      'error_log' => File.join(@dir, 'nginx-error.log'),
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                      'listen' => {
         
     | 
| 
      
 87 
     | 
    
         
            +
                        repeat: true,
         
     | 
| 
      
 88 
     | 
    
         
            +
                        '8080' => true,
         
     | 
| 
      
 89 
     | 
    
         
            +
                        '[::]:8080' => true,
         
     | 
| 
      
 90 
     | 
    
         
            +
                        '4433 ssl http2' => @ssl ? true : nil,
         
     | 
| 
      
 91 
     | 
    
         
            +
                        '[::]:4433 ssl http2' => @ssl ? true : nil,
         
     | 
| 
      
 92 
     | 
    
         
            +
                      },
         
     | 
| 
      
 93 
     | 
    
         
            +
                      'server_name' => (@hosts + @subdomains).join(' '),
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                      'gzip' => 'on',
         
     | 
| 
      
 96 
     | 
    
         
            +
                      'gzip_types' => 'application/javascript application/json text/css text/plain',
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                      'add_header' => {
         
     | 
| 
      
 99 
     | 
    
         
            +
                        repeat: true,
         
     | 
| 
      
 100 
     | 
    
         
            +
                        'Referrer-Policy' => 'same-origin',
         
     | 
| 
      
 101 
     | 
    
         
            +
                        'X-Frame-Options' => 'DENY',
         
     | 
| 
      
 102 
     | 
    
         
            +
                        'X-XSS-Protection' => '\'1; mode=block\'',
         
     | 
| 
      
 103 
     | 
    
         
            +
                        'X-Content-Type-Options' => 'nosniff',
         
     | 
| 
      
 104 
     | 
    
         
            +
                      },
         
     | 
| 
      
 105 
     | 
    
         
            +
                    }, @ssl ? @ssl.config : {}).merge!(
         
     | 
| 
      
 106 
     | 
    
         
            +
                      'location /' => {
         
     | 
| 
      
 107 
     | 
    
         
            +
                        raw: """
         
     | 
| 
      
 108 
     | 
    
         
            +
                          if ($host !~ ^#{hosts_subdomains_regex}$) { return 404; }
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                          set $r 0;
         
     | 
| 
      
 111 
     | 
    
         
            +
                          set $s $scheme;
         
     | 
| 
      
 112 
     | 
    
         
            +
                          set $h $host;
         
     | 
| 
      
 113 
     | 
    
         
            +
                          set $p '';
         
     | 
| 
      
 114 
     | 
    
         
            +
                          set $u '';
         
     | 
| 
      
 115 
     | 
    
         
            +
                          set $q '';
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                          #{if @www.nil? && @one_host == false
         
     | 
| 
      
 118 
     | 
    
         
            +
                            nil
         
     | 
| 
      
 119 
     | 
    
         
            +
                          elsif @www.nil? && @one_host == true
         
     | 
| 
      
 120 
     | 
    
         
            +
                            "if ($host !~ ^(www.)?#{host_subdomains_regex}$) { set $h $1#{@host}; set $r 1; }"
         
     | 
| 
      
 121 
     | 
    
         
            +
                          elsif @www == false && @one_host == false
         
     | 
| 
      
 122 
     | 
    
         
            +
                            "if ($host ~ ^www.(.+)$) { set $h $1; set $r 1; }"
         
     | 
| 
      
 123 
     | 
    
         
            +
                          elsif @www == false && @one_host == true
         
     | 
| 
      
 124 
     | 
    
         
            +
                            "if ($host !~ ^#{host_subdomains_regex}$) { set $h #{@host}; set $r 1; }"
         
     | 
| 
      
 125 
     | 
    
         
            +
                          elsif @www == true && @one_host == false
         
     | 
| 
      
 126 
     | 
    
         
            +
                            "if ($host !~ ^www.(.+)$) { set $h $1; set $r 1; }"
         
     | 
| 
      
 127 
     | 
    
         
            +
                          elsif @www == true && @one_host == true
         
     | 
| 
      
 128 
     | 
    
         
            +
                            "if ($host !~ ^www.#{host_subdomains_regex}$) { set $h www.#{@host}; set $r 1; }"
         
     | 
| 
      
 129 
     | 
    
         
            +
                          end}
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                          if ($scheme = #{@other_scheme}) { set $s #{@scheme}; set $r 1; }
         
     | 
| 
      
 132 
     | 
    
         
            +
                          if ($http_host ~ :[0-9]+$) { set $p :#{@ssl ? '4433' : '8080'}; }
         
     | 
| 
      
 133 
     | 
    
         
            +
                          if ($request_uri ~ ^([^\\?]+)(\\?+.*)?$) { set $u $1; set $q $2; }
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                          #{'if ($u ~ //) { set $u $uri; set $r 1; }' if @multiple_slashes == false}
         
     | 
| 
      
 136 
     | 
    
         
            +
                          #{'if ($q ~ ^\?\?+(.*)$) { set $q ?$1; set $r 1; }' if @multiple_question_marks == false}
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                          #{if @trailing_question_mark == false
         
     | 
| 
      
 139 
     | 
    
         
            +
                            'if ($q ~ \?+$) { set $q \'\'; set $r 1; }'
         
     | 
| 
      
 140 
     | 
    
         
            +
                          elsif @trailing_question_mark == true
         
     | 
| 
      
 141 
     | 
    
         
            +
                            'if ($q !~ .) { set $q ?; set $r 1; }'
         
     | 
| 
      
 142 
     | 
    
         
            +
                          end}
         
     | 
| 
      
 143 
     | 
    
         
            +
                          #{if @trailing_slash == false
         
     | 
| 
      
 144 
     | 
    
         
            +
                            'if ($u ~ (.+?)/+$) { set $u $1; set $r 1; }'
         
     | 
| 
      
 145 
     | 
    
         
            +
                          elsif @trailing_slash == true
         
     | 
| 
      
 146 
     | 
    
         
            +
                            'if ($u ~ [^/]$) { set $u $u/; set $r 1; }'
         
     | 
| 
      
 147 
     | 
    
         
            +
                          end}
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                          set $mr $request_method$r;
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                          if ($mr ~ ^(GET|HEAD)1$) { return 301 $s://$h$p$u$q; }
         
     | 
| 
      
 152 
     | 
    
         
            +
                          if ($mr ~ 1$) { return 308 $s://$h$p$u$q; }
         
     | 
| 
      
 153 
     | 
    
         
            +
                        """.strip.gsub(/^ +/, '').gsub(/\n{3,}/, "\n\n"),
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                        'proxy_pass' => "http://#{@host}",
         
     | 
| 
      
 156 
     | 
    
         
            +
                        'proxy_redirect' => 'off',
         
     | 
| 
      
 157 
     | 
    
         
            +
                        'proxy_set_header' => {
         
     | 
| 
      
 158 
     | 
    
         
            +
                          repeat: true,
         
     | 
| 
      
 159 
     | 
    
         
            +
                          'Host' => @host,
         
     | 
| 
      
 160 
     | 
    
         
            +
                          'X-Real-IP' => '$remote_addr',
         
     | 
| 
      
 161 
     | 
    
         
            +
                          'X-Forwarded-For' => '$proxy_add_x_forwarded_for',
         
     | 
| 
      
 162 
     | 
    
         
            +
                          'X-Forwarded-Proto' => @ssl ? 'https' : 'http',
         
     | 
| 
      
 163 
     | 
    
         
            +
                          'X-Forwarded-Port' => @ssl ? '443' : '80',
         
     | 
| 
      
 164 
     | 
    
         
            +
                        },
         
     | 
| 
      
 165 
     | 
    
         
            +
                      },
         
     | 
| 
      
 166 
     | 
    
         
            +
                    ),
         
     | 
| 
      
 167 
     | 
    
         
            +
                  }
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                  Util.deep_merge!(config['server'], @additional_config)
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                  config
         
     | 
| 
      
 172 
     | 
    
         
            +
                end
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                def write_config
         
     | 
| 
      
 175 
     | 
    
         
            +
                  File.open(@config_file_inactive, 'w') do |file|
         
     | 
| 
      
 176 
     | 
    
         
            +
                    file.write(self.class.to_nginx_config(config))
         
     | 
| 
      
 177 
     | 
    
         
            +
                  end
         
     | 
| 
      
 178 
     | 
    
         
            +
                end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                def activate_config
         
     | 
| 
      
 181 
     | 
    
         
            +
                  FileUtils.mv(@config_file_inactive, @config_file_active)
         
     | 
| 
      
 182 
     | 
    
         
            +
                end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                def deactivate_config
         
     | 
| 
      
 185 
     | 
    
         
            +
                  FileUtils.mv(@config_file_active, @config_file_inactive) if File.exists?(@config_file_active)
         
     | 
| 
      
 186 
     | 
    
         
            +
                end
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                def ensure_host_entries
         
     | 
| 
      
 189 
     | 
    
         
            +
                  content = File.read('/etc/hosts')
         
     | 
| 
      
 190 
     | 
    
         
            +
                  missing_entries = (@hosts + @subdomains).each_with_object([]) do |h, a|
         
     | 
| 
      
 191 
     | 
    
         
            +
                    a << h unless content.include?(" #{h}\n")
         
     | 
| 
      
 192 
     | 
    
         
            +
                  end
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                  return if missing_entries.empty?
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                  log('Writing host entries to /etc/hosts...')
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                  run(
         
     | 
| 
      
 199 
     | 
    
         
            +
                    <<~CMD
         
     | 
| 
      
 200 
     | 
    
         
            +
                      sudo sh -c 'printf "
         
     | 
| 
      
 201 
     | 
    
         
            +
                      #{missing_entries.map { |h| "127.0.0.1 #{h}\n::1       #{h}"}.join("\n")}
         
     | 
| 
      
 202 
     | 
    
         
            +
                      " >> /etc/hosts'
         
     | 
| 
      
 203 
     | 
    
         
            +
                    CMD
         
     | 
| 
      
 204 
     | 
    
         
            +
                  )
         
     | 
| 
      
 205 
     | 
    
         
            +
                end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                def ensure_include
         
     | 
| 
      
 208 
     | 
    
         
            +
                  config_file = `nginx -t 2>&1`[TEST_CONFIG_REGEX, :config]
         
     | 
| 
      
 209 
     | 
    
         
            +
                  config_content = File.read(config_file)
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
                  if config_content !~ INCLUDE_REGEX
         
     | 
| 
      
 212 
     | 
    
         
            +
                    File.write(config_file, config_content.sub(/^( *http *{)( *\n?)( *)/,
         
     | 
| 
      
 213 
     | 
    
         
            +
                      "\\1\\2\\3include #{ACTIVE_CONFIG_PATTERN};\n\n\\3"))
         
     | 
| 
      
 214 
     | 
    
         
            +
                  end
         
     | 
| 
      
 215 
     | 
    
         
            +
                end
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                def self.to_nginx_config(hash, indent: 0, repeat: nil)
         
     | 
| 
      
 218 
     | 
    
         
            +
                  hash.each_with_object(+'') do |(k, v), config|
         
     | 
| 
      
 219 
     | 
    
         
            +
                    next if v.nil?
         
     | 
| 
      
 220 
     | 
    
         
            +
                    next if k == :repeat
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                    config << (
         
     | 
| 
      
 223 
     | 
    
         
            +
                      if v.kind_of?(Hash)
         
     | 
| 
      
 224 
     | 
    
         
            +
                        if v[:repeat]
         
     | 
| 
      
 225 
     | 
    
         
            +
                          to_nginx_config(v, indent: indent, repeat: k)
         
     | 
| 
      
 226 
     | 
    
         
            +
                        else
         
     | 
| 
      
 227 
     | 
    
         
            +
                          "#{' ' * indent}#{k} {\n#{to_nginx_config(v, indent: indent + 2)}#{' ' * indent}}\n"
         
     | 
| 
      
 228 
     | 
    
         
            +
                        end
         
     | 
| 
      
 229 
     | 
    
         
            +
                      elsif k == :raw
         
     | 
| 
      
 230 
     | 
    
         
            +
                        "#{v.gsub(/^(?=.)/, ' ' * indent)}\n\n"
         
     | 
| 
      
 231 
     | 
    
         
            +
                      else
         
     | 
| 
      
 232 
     | 
    
         
            +
                        "#{' ' * indent}#{"#{repeat} " if repeat}#{k}#{" #{v}" unless v == true};\n"
         
     | 
| 
      
 233 
     | 
    
         
            +
                      end
         
     | 
| 
      
 234 
     | 
    
         
            +
                    )
         
     | 
| 
      
 235 
     | 
    
         
            +
                  end
         
     | 
| 
      
 236 
     | 
    
         
            +
                end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                def self.plist
         
     | 
| 
      
 239 
     | 
    
         
            +
                  super(
         
     | 
| 
      
 240 
     | 
    
         
            +
                    <<~EOS
         
     | 
| 
      
 241 
     | 
    
         
            +
                      <key>ProgramArguments</key>
         
     | 
| 
      
 242 
     | 
    
         
            +
                      <array>
         
     | 
| 
      
 243 
     | 
    
         
            +
                        <string>/usr/local/opt/nginx/bin/nginx</string>
         
     | 
| 
      
 244 
     | 
    
         
            +
                        <string>-g</string>
         
     | 
| 
      
 245 
     | 
    
         
            +
                        <string>daemon off;</string>
         
     | 
| 
      
 246 
     | 
    
         
            +
                      </array>
         
     | 
| 
      
 247 
     | 
    
         
            +
                      <key>StandardOutPath</key>
         
     | 
| 
      
 248 
     | 
    
         
            +
                      <string>/usr/local/var/log/nginx/access.log</string>
         
     | 
| 
      
 249 
     | 
    
         
            +
                      <key>StandardErrorPath</key>
         
     | 
| 
      
 250 
     | 
    
         
            +
                      <string>/usr/local/var/log/nginx/error.log</string>
         
     | 
| 
      
 251 
     | 
    
         
            +
                    EOS
         
     | 
| 
      
 252 
     | 
    
         
            +
                  )
         
     | 
| 
      
 253 
     | 
    
         
            +
                end
         
     | 
| 
      
 254 
     | 
    
         
            +
              end
         
     | 
| 
      
 255 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,110 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require('time')
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Potluck
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Nginx < Dish
         
     | 
| 
      
 7 
     | 
    
         
            +
                class SSL
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # Based on https://hackernoon.com/how-properly-configure-nginx-server-for-tls-sg1d3udt
         
     | 
| 
      
 9 
     | 
    
         
            +
                  DEFAULT_CONFIG = {
         
     | 
| 
      
 10 
     | 
    
         
            +
                    'ssl_ciphers' => 'ECDH+AESGCM:ECDH+AES256-CBC:ECDH+AES128-CBC:DH+3DES:!ADH:!AECDH:!MD5',
         
     | 
| 
      
 11 
     | 
    
         
            +
                    'ssl_prefer_server_ciphers' => 'on',
         
     | 
| 
      
 12 
     | 
    
         
            +
                    'ssl_protocols' => 'TLSv1.2 TLSv1.3',
         
     | 
| 
      
 13 
     | 
    
         
            +
                    'ssl_session_cache' => 'shared:SSL:40m',
         
     | 
| 
      
 14 
     | 
    
         
            +
                    'ssl_session_tickets' => 'on',
         
     | 
| 
      
 15 
     | 
    
         
            +
                    'ssl_session_timeout' => '4h',
         
     | 
| 
      
 16 
     | 
    
         
            +
                    'add_header' => {
         
     | 
| 
      
 17 
     | 
    
         
            +
                      repeat: true,
         
     | 
| 
      
 18 
     | 
    
         
            +
                      'Strict-Transport-Security' => '\'max-age=31536000; includeSubDomains\' always',
         
     | 
| 
      
 19 
     | 
    
         
            +
                    }.freeze,
         
     | 
| 
      
 20 
     | 
    
         
            +
                  }.freeze
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  CERT_DAYS = 365
         
     | 
| 
      
 23 
     | 
    
         
            +
                  CERT_RENEW_DAYS = 14
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  attr_reader(:csr_file, :key_file, :crt_file, :dhparam_file, :config)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def initialize(nginx, dir, host, crt_file: nil, key_file: nil, dhparam_file: nil,
         
     | 
| 
      
 28 
     | 
    
         
            +
                      config: {})
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @nginx = nginx
         
     | 
| 
      
 30 
     | 
    
         
            +
                    @dir = dir
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @host = host
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    @auto_generated = !crt_file && !key_file && !dhparam_file
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    if !@auto_generated && (!crt_file || !key_file || !dhparam_file)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      raise('Must supply values for all three or none: crt_file, key_file, dhparam_file')
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    @csr_file = File.join(@dir, "#{@host}.csr").freeze
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @crt_file = crt_file || File.join(@dir, "#{@host}.crt").freeze
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @key_file = key_file || File.join(@dir, "#{@host}.key").freeze
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @dhparam_file = dhparam_file || File.join(@dir, 'dhparam.pem').freeze
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    @config = {
         
     | 
| 
      
 45 
     | 
    
         
            +
                      'ssl_certificate' => @crt_file,
         
     | 
| 
      
 46 
     | 
    
         
            +
                      'ssl_certificate_key' => @key_file,
         
     | 
| 
      
 47 
     | 
    
         
            +
                      'ssl_dhparam' => @dhparam_file,
         
     | 
| 
      
 48 
     | 
    
         
            +
                      'ssl_stapling' => ('on' unless @auto_generated),
         
     | 
| 
      
 49 
     | 
    
         
            +
                      'ssl_stapling_verify' => ('on' unless @auto_generated),
         
     | 
| 
      
 50 
     | 
    
         
            +
                    }.merge!(DEFAULT_CONFIG).merge!(config)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def ensure_files
         
     | 
| 
      
 54 
     | 
    
         
            +
                    return if !@auto_generated || (
         
     | 
| 
      
 55 
     | 
    
         
            +
                      File.exists?(@csr_file) &&
         
     | 
| 
      
 56 
     | 
    
         
            +
                      File.exists?(@key_file) &&
         
     | 
| 
      
 57 
     | 
    
         
            +
                      File.exists?(@crt_file) &&
         
     | 
| 
      
 58 
     | 
    
         
            +
                      File.exists?(@dhparam_file) &&
         
     | 
| 
      
 59 
     | 
    
         
            +
                      (Time.parse(
         
     | 
| 
      
 60 
     | 
    
         
            +
                        @nginx.run("openssl x509 -enddate -noout -in #{@crt_file}").sub('notAfter=', '')
         
     | 
| 
      
 61 
     | 
    
         
            +
                      ) - Time.now) >= CERT_RENEW_DAYS * 24 * 60 * 60
         
     | 
| 
      
 62 
     | 
    
         
            +
                    )
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    @nginx.log('Generating SSL files...')
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    @nginx.run("openssl genrsa -out #{@key_file} 4096", redirect_stderr: false)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    @nginx.run("openssl req -out #{@csr_file} -key #{@key_file} -new -sha256 -config /dev/stdin <<< "\
         
     | 
| 
      
 68 
     | 
    
         
            +
                      "'#{openssl_config}'", redirect_stderr: false)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    @nginx.run("openssl x509 -in #{@csr_file} -out #{@crt_file} -signkey #{@key_file} -days "\
         
     | 
| 
      
 70 
     | 
    
         
            +
                      "#{CERT_DAYS} -req -sha256 -extensions req_ext -extfile /dev/stdin <<< '#{openssl_config}'",
         
     | 
| 
      
 71 
     | 
    
         
            +
                      redirect_stderr: false)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    @nginx.run("openssl dhparam -out #{@dhparam_file} 2048", redirect_stderr: false)
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                    if IS_MACOS
         
     | 
| 
      
 75 
     | 
    
         
            +
                      @nginx.log('Adding cert to keychain...')
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                      @nginx.run(
         
     | 
| 
      
 78 
     | 
    
         
            +
                        "sudo security delete-certificate -t -c #{@host} 2>&1 || "\
         
     | 
| 
      
 79 
     | 
    
         
            +
                        "sudo security delete-certificate -c #{@host} 2>&1 || :"
         
     | 
| 
      
 80 
     | 
    
         
            +
                      )
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                      @nginx.run("sudo security add-trusted-cert -d -r trustRoot -k "\
         
     | 
| 
      
 83 
     | 
    
         
            +
                        "/Library/Keychains/System.keychain #{@crt_file}")
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  private
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  def openssl_config
         
     | 
| 
      
 90 
     | 
    
         
            +
                    <<~EOS
         
     | 
| 
      
 91 
     | 
    
         
            +
                      [ req ]
         
     | 
| 
      
 92 
     | 
    
         
            +
                      prompt             = no
         
     | 
| 
      
 93 
     | 
    
         
            +
                      default_bits       = 4096
         
     | 
| 
      
 94 
     | 
    
         
            +
                      distinguished_name = req_distinguished_name
         
     | 
| 
      
 95 
     | 
    
         
            +
                      req_extensions     = req_ext
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                      [ req_distinguished_name ]
         
     | 
| 
      
 98 
     | 
    
         
            +
                      commonName          = #{@host}
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                      [ req_ext ]
         
     | 
| 
      
 101 
     | 
    
         
            +
                      subjectAltName = @alt_names
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                      [alt_names]
         
     | 
| 
      
 104 
     | 
    
         
            +
                      DNS.1 = #{@host}
         
     | 
| 
      
 105 
     | 
    
         
            +
                      DNS.2 = *.#{@host}
         
     | 
| 
      
 106 
     | 
    
         
            +
                    EOS
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
              end
         
     | 
| 
      
 110 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Potluck
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Nginx
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Util
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def self.deep_merge!(*hashes, arrays: false)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    hash = hashes[0]
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    hashes[1..-1].each do |other_hash|
         
     | 
| 
      
 10 
     | 
    
         
            +
                      other_hash.each do |key, other_value|
         
     | 
| 
      
 11 
     | 
    
         
            +
                        this_value = hash[key]
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                        if this_value.kind_of?(Hash) && other_value.kind_of?(Hash)
         
     | 
| 
      
 14 
     | 
    
         
            +
                          deep_merge!(this_value, other_value, arrays: arrays)
         
     | 
| 
      
 15 
     | 
    
         
            +
                        elsif arrays && this_value.kind_of?(Array)
         
     | 
| 
      
 16 
     | 
    
         
            +
                          hash[key] |= Array(other_value)
         
     | 
| 
      
 17 
     | 
    
         
            +
                        else
         
     | 
| 
      
 18 
     | 
    
         
            +
                          hash[key] = other_value
         
     | 
| 
      
 19 
     | 
    
         
            +
                        end
         
     | 
| 
      
 20 
     | 
    
         
            +
                      end
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    hash
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: potluck-nginx
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Nate Pickens
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire:
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2021-03-27 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: potluck
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - '='
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: 0.0.1
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - '='
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: 0.0.1
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: minitest
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: 5.11.2
         
     | 
| 
      
 48 
     | 
    
         
            +
                - - "<"
         
     | 
| 
      
 49 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 50 
     | 
    
         
            +
                    version: 6.0.0
         
     | 
| 
      
 51 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 52 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 53 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 54 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 55 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 56 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 57 
     | 
    
         
            +
                    version: 5.11.2
         
     | 
| 
      
 58 
     | 
    
         
            +
                - - "<"
         
     | 
| 
      
 59 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 60 
     | 
    
         
            +
                    version: 6.0.0
         
     | 
| 
      
 61 
     | 
    
         
            +
            description: An extension to the Potluck gem that provides control over the Nginx
         
     | 
| 
      
 62 
     | 
    
         
            +
              process and its configuration files from Ruby.
         
     | 
| 
      
 63 
     | 
    
         
            +
            email:
         
     | 
| 
      
 64 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 65 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 66 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 67 
     | 
    
         
            +
            files:
         
     | 
| 
      
 68 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 69 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 70 
     | 
    
         
            +
            - lib/potluck/nginx.rb
         
     | 
| 
      
 71 
     | 
    
         
            +
            - lib/potluck/nginx/ssl.rb
         
     | 
| 
      
 72 
     | 
    
         
            +
            - lib/potluck/nginx/util.rb
         
     | 
| 
      
 73 
     | 
    
         
            +
            homepage: https://github.com/npickens/potluck/tree/master/potluck-nginx
         
     | 
| 
      
 74 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 75 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 76 
     | 
    
         
            +
            metadata:
         
     | 
| 
      
 77 
     | 
    
         
            +
              allowed_push_host: https://rubygems.org
         
     | 
| 
      
 78 
     | 
    
         
            +
              homepage_uri: https://github.com/npickens/potluck/tree/master/potluck-nginx
         
     | 
| 
      
 79 
     | 
    
         
            +
              source_code_uri: https://github.com/npickens/potluck/tree/master/potluck-nginx
         
     | 
| 
      
 80 
     | 
    
         
            +
            post_install_message:
         
     | 
| 
      
 81 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 82 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 83 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 84 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 85 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 86 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 87 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 88 
     | 
    
         
            +
                  version: 2.5.8
         
     | 
| 
      
 89 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 90 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 91 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 92 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 93 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 94 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 95 
     | 
    
         
            +
            rubygems_version: 3.2.3
         
     | 
| 
      
 96 
     | 
    
         
            +
            signing_key:
         
     | 
| 
      
 97 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 98 
     | 
    
         
            +
            summary: A Ruby manager for Nginx.
         
     | 
| 
      
 99 
     | 
    
         
            +
            test_files: []
         
     |