letsencrypt_webfaction 0.0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7df37c878990ab6cc66c72d383fd790c1438ea80
4
- data.tar.gz: 7f90d70c80b4f1522f725bdb76289a7673cde3cc
3
+ metadata.gz: 7ce33f9963c0f2f176f271677a4940058999553f
4
+ data.tar.gz: 0d3e010e9f36feeb6ad4b683614fd8bcfee88988
5
5
  SHA512:
6
- metadata.gz: c3ead0e1aa11a3635136056379479e5e7a4124b85ef50612320066cecca7ffc1699840fac19a1a0eada1cfd3d065e4429e833ac7a519d87ae503cde3cf1a5768
7
- data.tar.gz: 72dfad675873758f4179382499863e72735051b6d7be902346584510331b7494b5805f3ba91f6b714912b7ff17634de907c0e9e65961cbf5a5966b7948e653af
6
+ metadata.gz: 97a8d46981d1a5d2252be5a832e6f9ec68be1d61864a3166a9f7272d7c246098176a64f9177e5529710b5ac7dd7a29bf381a62f994b2e8740c225f49945602a2
7
+ data.tar.gz: 675c9b21c9f794794f316a9194ea0edca89d7810b9ad02dc1e40e9f53a2c7c342f361b822dcafbde3e1530d3fc4a162d752a379e2aff1b72264717ac115e80e2
@@ -0,0 +1,24 @@
1
+ ---
2
+ engines:
3
+ duplication:
4
+ enabled: true
5
+ config:
6
+ languages:
7
+ - ruby
8
+ fixme:
9
+ enabled: true
10
+ rubocop:
11
+ enabled: true
12
+ checks:
13
+ Rubocop/Rails: false
14
+ ratings:
15
+ paths:
16
+ - "**.inc"
17
+ - "**.js"
18
+ - "**.jsx"
19
+ - "**.module"
20
+ - "**.php"
21
+ - "**.py"
22
+ - "**.rb"
23
+ exclude_paths:
24
+ - spec/
data/.gitignore CHANGED
@@ -7,3 +7,6 @@
7
7
 
8
8
  # Ignore code coverage output.
9
9
  /coverage
10
+
11
+ # Ignore vim locks
12
+ *.swp
@@ -35,3 +35,9 @@ Style/Send:
35
35
  # If you interpolate a literal, just include it in the string itself.
36
36
  Lint/LiteralInInterpolation:
37
37
  Enabled: true
38
+
39
+ # Personal preference. Makes the diffs smaller.
40
+ Style/TrailingCommaInLiteral:
41
+ EnforcedStyleForMultiline: consistent_comma
42
+ Style/TrailingCommaInArguments:
43
+ EnforcedStyleForMultiline: consistent_comma
@@ -0,0 +1,11 @@
1
+ v0.0.3
2
+
3
+ * Updates to readme.
4
+
5
+ v0.0.2
6
+
7
+ * Fix a bug related to Gem pathing and the defaults.yml file.
8
+
9
+ v0.0.1
10
+
11
+ * Initial release.
@@ -0,0 +1,21 @@
1
+ # The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 William Johnston
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -2,13 +2,45 @@
2
2
 
3
3
  LetsEncrypt utility client for WebFaction hosts.
4
4
 
5
- This tool simplifies the manual process of using LetsEncrypt on Webfaction hosts. It can be added to cron where it will validate your domains automatically, place the generated certificates in a common folder, and then email you directions and example text to send the WebFaction support team.
5
+ This tool simplifies the manual process of using LetsEncrypt on Webfaction hosts. It can be added to cron where it will validate your domains automatically, place the generated certificates in a common folder, and then email the Webfaction support team to request installation, also notifying you.
6
6
 
7
7
  [![Build Status](https://travis-ci.org/will-in-wi/letsencrypt-webfaction.svg?branch=master)](https://travis-ci.org/will-in-wi/letsencrypt-webfaction)
8
8
 
9
+ [![Gem Version](https://badge.fury.io/rb/letsencrypt_webfaction.svg)](https://badge.fury.io/rb/letsencrypt_webfaction)
10
+
11
+ [![Code Climate](https://codeclimate.com/github/will-in-wi/letsencrypt-webfaction/badges/gpa.svg)](https://codeclimate.com/github/will-in-wi/letsencrypt-webfaction)
12
+
9
13
  ## Installation
10
14
 
11
- Because WebFaction has an unusual Ruby setup with the default Ruby as 1.8, I recommend that you [set up RBEnv](https://github.com/rbenv/rbenv) and [Ruby Build](https://github.com/rbenv/ruby-build#readme) on your WebFaction server to run this script.
15
+ This utility works on [CentOS 6 and 7 boxes](https://docs.webfaction.com/user-guide/server.html#finding-your-server-s-operating-system). The CentOS 5 systems do not have a new enough OpenSSL to include the algorithms required. You may be able to make this work using rbenv and compiling openssl yourself.
16
+
17
+ You can install LetsEncrypt Webfaction using the system Ruby or using RBEnv.
18
+
19
+ ### System Ruby
20
+
21
+ This is the simpler method and is preferred.
22
+
23
+ Run the following command to install:
24
+
25
+ ```sh
26
+ GEM_HOME=$HOME/.letsencrypt_webfaction/gems RUBYLIB=$GEM_HOME/lib gem2.2 install letsencrypt_webfaction
27
+ ```
28
+
29
+ Add the following to `~/.bash_profile`:
30
+
31
+ ```sh
32
+ function letsencrypt_webfaction {
33
+ PATH=$PATH:$GEM_HOME/bin GEM_HOME=$HOME/.letsencrypt_webfaction/gems RUBYLIB=$GEM_HOME/lib ruby2.2 $HOME/.letsencrypt_webfaction/gems/bin/letsencrypt_webfaction $*
34
+ }
35
+ ```
36
+
37
+ Now, you can run `letsencrypt_webfaction` from the shell.
38
+
39
+ ### RBEnv
40
+
41
+ This method is useful if you are already using RBEnv to manage Ruby.
42
+
43
+ Follow the instructions to [set up RBEnv](https://github.com/rbenv/rbenv) and [Ruby Build](https://github.com/rbenv/ruby-build#readme) on your WebFaction server.
12
44
 
13
45
  Once you have done so, install Ruby 2.1+ (probably 2.3.0 at time of writing). Then set the local Ruby and install the Gem. Finally unset the local Ruby so that you don't run into problems.
14
46
 
@@ -22,7 +54,7 @@ Once you have done so, install Ruby 2.1+ (probably 2.3.0 at time of writing). Th
22
54
 
23
55
  Basic example:
24
56
 
25
- $ letsencrypt_webfaction --contact me@example.com --domains example.com,www.example.com --public ~/webapps/myapp/public_html/
57
+ $ letsencrypt_webfaction --account_email me@example.com --domains example.com,www.example.com --public ~/webapps/myapp/public_html/
26
58
 
27
59
  To quickly get a list of parameters, you can call:
28
60
 
@@ -34,7 +66,10 @@ Normally, you will run the script manually once to get the certificate, and then
34
66
 
35
67
  Your cron task could look something like:
36
68
 
37
- 0 4 * */2 * cd /home/williaminwi/Projects/letsencrypt-webfaction && RBENV_ROOT=~/.rbenv RBENV_VERSION=2.3.0 ~/.rbenv/bin/rbenv exec letsencrypt_webfaction --contact you@example.com --domains example.com,www.example.com --public ~/webapps/myapp/
69
+ # System Ruby Installation
70
+ 0 4 1 */2 * PATH=$PATH:$GEM_HOME/bin GEM_HOME=$HOME/.letsencrypt_webfaction/gems RUBYLIB=$GEM_HOME/lib ruby2.2 $HOME/.letsencrypt_webfaction/gems/bin/letsencrypt_webfaction --account_email you@example.com --domains example.com,www.example.com --public ~/webapps/myapp/
71
+ # RBEnv Installation
72
+ 0 4 1 */2 * RBENV_ROOT=~/.rbenv RBENV_VERSION=2.3.0 ~/.rbenv/bin/rbenv exec letsencrypt_webfaction --account_email you@example.com --domains example.com,www.example.com --public ~/webapps/myapp/
38
73
 
39
74
  This [would run](http://crontab.guru/#0_4_*_*/2_*) at 4 a.m. in Jan, Mar, May, Jul, Sep, and Nov. Certificates expire three months after issuance, so modify as desired.
40
75
 
@@ -56,9 +91,7 @@ This could be run automatically every two months.
56
91
 
57
92
  When the code runs, it places verification files into a public directory, validates the domains with LetsEncrypt (or your ACME provider), and then dumps the signed certificate and private key into an output folder. By default, the output folder is `~/le_certs/`, inside which it will create `[domain_name]/[timestamp]/`.
58
93
 
59
- After this is done, the utility will dump to stdout instructions regarding how to request that your new certs be installed by the WebFaction admins. This will include sample text and a link to https://help.webfaction.com/.
60
-
61
- If you use Cron, you should set `MAILTO=youremail@example.com` and `MAILFROM=username@servername.webfaction.com` at the top in order to receive the instructions. The [WebFaction docs](https://docs.webfaction.com/software/general.html#scheduling-tasks-cron) have more details about how to do this.
94
+ After this is done, the utility will email the cert installation request to Webfaction support and also copy you.
62
95
 
63
96
  If you see messages containing SyntaxErrors, you are most likely using an old version of Ruby. This utility requires Ruby 2.1+.
64
97
 
@@ -78,6 +111,8 @@ To run the script directly from the repository, use:
78
111
 
79
112
  To test certificate issuance, consider using the [LetsEncrypt staging server](https://community.letsencrypt.org/t/testing-against-the-lets-encrypt-staging-environment/6763). This doesn't have the 5 certs per domain every 7 days rate limit. You can add the `--endpoint https://acme-staging.api.letsencrypt.org/` parameter to do so.
80
113
 
114
+ You will probably also want to use the argument `--support_email ""` which will keep support from actually being contacted. Alternately, set the `support_email` address to be yourself.
115
+
81
116
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
82
117
 
83
118
  To install this gem onto your local machine, run `bin/rake install`. To release a new version, update the version number in `lib/letsencrypt_webfaction.rb`, and then run `bin/rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). This project uses [Semantic Versioning](http://semver.org/).
@@ -3,5 +3,8 @@ key_size: 4096
3
3
  endpoint: 'https://acme-v01.api.letsencrypt.org/'
4
4
  domains: []
5
5
  public: ''
6
- contact: ''
7
6
  output_dir: '~/le_certs/'
7
+ support_email: 'support@webfaction.com'
8
+ account_email: ''
9
+ admin_notification_email: '' # Defaults to the value given in account_email.
10
+ letsencrypt_account_email: '' # Defaults to the value given in account_email.
@@ -1,6 +1,8 @@
1
+ # See config.defaults.yml for all available settings.
2
+
1
3
  key_size: 4096
2
4
  endpoint: 'https://acme-v01.api.letsencrypt.org/'
3
- contact: 'me@example.com'
5
+ account_email: 'me@example.com'
4
6
  domains:
5
7
  - 'example.com'
6
8
  - 'www.example.com'
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'letsencrypt_webfaction/application'
4
4
 
5
- LetsencryptWebfaction::Application.new.run!
5
+ LetsencryptWebfaction::Application.new(ARGV).run!
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.required_ruby_version = '>= 2.1.0'
28
28
 
29
29
  spec.add_runtime_dependency 'acme-client', '~> 0.3.0'
30
+ spec.add_runtime_dependency 'pony', '~> 1.11'
30
31
 
31
32
  spec.add_development_dependency 'bundler', '~> 1.11'
32
33
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -34,4 +35,5 @@ Gem::Specification.new do |spec|
34
35
  spec.add_development_dependency 'rubocop', '~> 0.37'
35
36
  spec.add_development_dependency 'simplecov', '~> 0.11'
36
37
  spec.add_development_dependency 'pry', '~> 0.10'
38
+ spec.add_development_dependency 'pry-byebug', '~> 3.3'
37
39
  end
@@ -1,3 +1,3 @@
1
1
  module LetsencryptWebfaction
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -5,11 +5,12 @@ require 'letsencrypt_webfaction/args_parser'
5
5
  require 'letsencrypt_webfaction/domain_validator'
6
6
  require 'letsencrypt_webfaction/certificate_writer'
7
7
  require 'letsencrypt_webfaction/instructions'
8
+ require 'letsencrypt_webfaction/emailer'
8
9
 
9
10
  module LetsencryptWebfaction
10
11
  class Application
11
- def initialize
12
- @options = LetsencryptWebfaction::ArgsParser.new(ARGV)
12
+ def initialize(args)
13
+ @options = LetsencryptWebfaction::ArgsParser.new(args)
13
14
  end
14
15
 
15
16
  def run!
@@ -25,12 +26,16 @@ module LetsencryptWebfaction
25
26
  # Write the obtained certificates.
26
27
  certificate_writer.write!
27
28
 
28
- # Dump help text.
29
- puts instructions.message
29
+ # Send emails.
30
+ emailer.send!
30
31
  end
31
32
 
32
33
  private
33
34
 
35
+ def emailer
36
+ @emails ||= LetsencryptWebfaction::Emailer.new instructions, support_email: @options.support_email, account_email: @options.account_email, notification_email: @options.admin_notification_email
37
+ end
38
+
34
39
  def instructions
35
40
  @instructions ||= LetsencryptWebfaction::Instructions.new certificate_writer.output_dir, @options.domains
36
41
  end
@@ -62,7 +67,7 @@ module LetsencryptWebfaction
62
67
 
63
68
  def register_key!
64
69
  # If the private key is not known to the server, we need to register it for the first time.
65
- registration = client.register(contact: "mailto:#{@options.contact}")
70
+ registration = client.register(contact: "mailto:#{@options.letsencrypt_account_email}")
66
71
 
67
72
  # You'll may need to agree to the term (that's up the to the server to require it or not but boulder does by default)
68
73
  registration.agree_terms
@@ -70,8 +75,7 @@ module LetsencryptWebfaction
70
75
 
71
76
  def validate_options!
72
77
  return if @options.valid?
73
- puts @options.errors.values.join("\n")
74
- exit
78
+ raise ArgumentError, @options.errors.values.join("\n")
75
79
  end
76
80
 
77
81
  def private_key
@@ -15,10 +15,13 @@ module LetsencryptWebfaction
15
15
  FIELDS = [
16
16
  Field::IntegerField.new(:key_size, 'Size of private key (e.g. 4096)', [DefinedValuesValidator.new(VALID_KEY_SIZES)]),
17
17
  Field.new(:endpoint, 'ACME endpoint (e.g. https://acme-v01.api.letsencrypt.org/)', [StringValidator.new]),
18
- Field.new(:contact, 'Email address to notify on renewal', [StringValidator.new]),
19
18
  Field::ListField.new(:domains, 'Comma separated list of domains. The first one will be the common name.', [ArrayValidator.new]),
20
19
  Field.new(:public, 'Location on the filesystem served by the desired site (e.g. ~/webapps/myapp/public_html)', [StringValidator.new]),
21
- Field.new(:output_dir, 'Location on the filesystem to which the certs will be saved.', [StringValidator.new])
20
+ Field.new(:output_dir, 'Location on the filesystem to which the certs will be saved.', [StringValidator.new]),
21
+ Field.new(:support_email, 'The email address of the ISP support.', []),
22
+ Field.new(:account_email, 'The email address associated with your account.', [StringValidator.new]),
23
+ Field.new(:admin_notification_email, 'The email address associated with your account. Defaults to the value of account_email.', []),
24
+ Field.new(:letsencrypt_account_email, 'The email address associated with your account. Defaults to the value of account_email.', []),
22
25
  ].freeze
23
26
 
24
27
  # Set up getters.
@@ -97,6 +100,15 @@ module LetsencryptWebfaction
97
100
 
98
101
  def parse!
99
102
  opt_parser.parse!(@options)
103
+
104
+ # Set defaults from other fields.
105
+ if @admin_notification_email.nil? || @admin_notification_email == ''
106
+ @admin_notification_email = @account_email
107
+ end
108
+
109
+ if @letsencrypt_account_email.nil? || @letsencrypt_account_email == ''
110
+ @letsencrypt_account_email = @account_email
111
+ end
100
112
  end
101
113
  end
102
114
  end
@@ -0,0 +1,34 @@
1
+ require 'pony'
2
+
3
+ module LetsencryptWebfaction
4
+ class Emailer
5
+ SUBJECT_MESSAGE = 'New certificate installation'.freeze
6
+
7
+ def initialize(instructions, support_email: '', account_email: '', notification_email: '')
8
+ @instructions = instructions
9
+
10
+ raise Error, 'Missing account_email' if account_email == '' || account_email.nil?
11
+ raise Error, 'Missing notification_email' if notification_email == '' || notification_email.nil?
12
+
13
+ @support_email = support_email
14
+ @account_email = account_email
15
+ @notification_email = notification_email
16
+ end
17
+
18
+ def send!
19
+ send_to_support!
20
+ send_to_account!
21
+ end
22
+
23
+ def send_to_support!
24
+ return if @support_email.nil? || @support_email == ''
25
+ Pony.mail(to: @support_email, from: @account_email, subject: SUBJECT_MESSAGE, body: @instructions.instructions)
26
+ end
27
+
28
+ def send_to_account!
29
+ Pony.mail(to: @notification_email, from: @notification_email, subject: SUBJECT_MESSAGE, body: @instructions.full_message(support_email: @support_email != ''))
30
+ end
31
+
32
+ class Error < StandardError; end
33
+ end
34
+ end
@@ -5,17 +5,30 @@ module LetsencryptWebfaction
5
5
  @domains = domains
6
6
  end
7
7
 
8
- def message
9
- 'LetsEncrypt Webfaction has generated a new certificate for ' \
10
- "#{to_sentence @domains}. The certificates have been placed in " \
11
- "#{@output_dir}. You now need to request installation from the " \
12
- "WebFaction support team.\n\n" \
13
- 'Go to https://help.webfaction.com, log in, and paste the ' \
14
- "following text into a new ticket:\n\n" \
8
+ def context(support_email: true)
9
+ out = 'LetsEncrypt Webfaction has generated a new certificate for ' \
10
+ "#{to_sentence @domains}. The certificates have been placed in " \
11
+ "#{@output_dir}. "
12
+
13
+ out << if support_email
14
+ 'WebFaction support has been contacted with the following message:'
15
+ else
16
+ 'Go to https://help.webfaction.com, log in, and paste the ' \
17
+ 'following text into a new ticket:'
18
+ end
19
+
20
+ out
21
+ end
22
+
23
+ def instructions
15
24
  "Please apply the new certificate in #{@output_dir} to " \
16
25
  "#{to_sentence @domains}. Thanks!"
17
26
  end
18
27
 
28
+ def full_message(support_email: true)
29
+ context(support_email: support_email) + "\n\n" + instructions
30
+ end
31
+
19
32
  private
20
33
 
21
34
  # Borrowed (with simplifications) from ActiveSupport.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: letsencrypt_webfaction
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Johnston
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-02-06 00:00:00.000000000 Z
11
+ date: 2016-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acme-client
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: pony
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.11'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.11'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +122,20 @@ dependencies:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0.10'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-byebug
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.3'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.3'
111
139
  description: A tool to simplify the manual process of using LetsEncrypt on Webfaction
112
140
  hosts. It can be added to cron where it will validate your domains automatically,
113
141
  place the generated certs in a common folder, and then email you directions and
@@ -119,11 +147,14 @@ executables:
119
147
  extensions: []
120
148
  extra_rdoc_files: []
121
149
  files:
150
+ - ".codeclimate.yml"
122
151
  - ".gitignore"
123
152
  - ".rspec"
124
153
  - ".rubocop.yml"
125
154
  - ".travis.yml"
155
+ - CHANGELOG.md
126
156
  - Gemfile
157
+ - LICENSE.md
127
158
  - README.md
128
159
  - Rakefile
129
160
  - bin/console
@@ -144,6 +175,7 @@ files:
144
175
  - lib/letsencrypt_webfaction/args_parser/string_validator.rb
145
176
  - lib/letsencrypt_webfaction/certificate_writer.rb
146
177
  - lib/letsencrypt_webfaction/domain_validator.rb
178
+ - lib/letsencrypt_webfaction/emailer.rb
147
179
  - lib/letsencrypt_webfaction/instructions.rb
148
180
  homepage: https://github.com/will-in-wi/letsencrypt-webfaction
149
181
  licenses:
@@ -165,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
197
  version: '0'
166
198
  requirements: []
167
199
  rubyforge_project:
168
- rubygems_version: 2.5.1
200
+ rubygems_version: 2.5.2
169
201
  signing_key:
170
202
  specification_version: 4
171
203
  summary: LetsEncrypt utility client for WebFaction hosts.