Skip to content
lazylester edited this page Jun 16, 2019 · 19 revisions

1. Install acme_plugin gem

Add below line to your application's Gemfile:

gem 'acme_plugin'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install acme_plugin

2. Create configuration

Next, you have to create configuration (template below):

default: &default
  endpoint: 'https://acme-v01.api.letsencrypt.org/'
  email: '[email protected]'
  domain: "<%= ['example.com', 'www.example.com', 'mail.example.com'].join(' ') %>"

  # in Rails.root, path to private key
  private_key: 'key/keyfile.pem'

  # Private key stored in the database
  # private_key_in_db: true

  # in Rails.root, path where certificates will be stored
  # NOTE: on Heroku, this variable is ignored
  output_cert_dir: 'certificates'

  # in Rails.root, path where challenge token will be stored
  # in situations when database will not be used
  # NOTE: on Heroku, comment out this line and use the database
  challenge_dir_name: 'challenge'

production:
  # if 'cert_name' is set, the keys are saved with this name, if not the first string from key 'domain' will be used
  cert_name: 'production'
  <<: *default
  
development:
  # if 'cert_name' is set, the keys are saved with this name, if not the first string from key 'domain' will be used
  cert_name: 'development'
  <<: *default

test:
  # if 'cert_name' is set, the keys are saved with this name, if not the first string from key 'domain' will be used
  cert_name: 'test'
  <<: *default

and put it into Rails.root/config/acme_plugin.yml file.

Next you have to create directories used in private_key and output_cert_dir variables (if they does not exist yet):

mkdir key certificates

If DB wont be used for storing challenge token:

mkdir challenge

2a. Multiple domains

If you would like to generate certificate for multiple domains, ie. example.com, www.example.com, other.example.com then please add them separated by space. acme_plugin.yml supports erb syntax allowing key values to be generated when the rails app is initialized. This allows specifically for support for multiple semi-dynamic domains/subdomains (see above example) which could be pulled from the database if need be.

  domain: example.com www.example.com other.example.com

or

  domain: "<%= ['example.com', 'www.example.com', 'other.example.com'].join(' ') %>"

Please bear in mind that if you would like to generate certificate for multiple domains then you have to create symlinks between sub-domains and main domain www directory. For example:

+---- /var/www 
            |
            + --- example.com
                  ^  ^
                  |  |
                  |  + --- other1.example.com
                  |
                  + --- other2.example.com

It is because challenge verification is handled by the domain where the acme_plugin script has been installed and run. Symlinking and directories not necessary on Heroku.

3. Install acme_plugin migration

Skip this step if you are not using the database process.

NOTE: the database process is required on Heroku, as the filesystem is not shared between worker dynos and web dynos (thus the challenges cannot be accessed).

Run the two following commands to copy acme_plugin database migrations to your application and create acme_plugin_challenges and acme_plugin_settings tables:

$ rake acme_plugin:install:migrations
$ rake db:migrate

4. Create private key

If you don't have previously generated private key you can create it by running following command (Note: Please use key size between 2048 - 4096 bits, because Let's Encrypt server doesn't allow keys larger than 4096 bits)

$ openssl genrsa 4096 > key/keyfile.pem

5. Create output directory

output_cert_dir must exist - it wont be created automaticaly (when running on Heroku output directory will be ignored - certificates will be displayed on console instead of saving on disk).

6. Mount acme_plugin engine

Next, you have to mount acme_plugin engine in routes.rb:

Rails.application.routes.draw do
  mount AcmePlugin::Engine, at: '/'  # It must be at root level

  # Other routes...

end

7. Restart your application

$ touch tmp/restart.txt