{"id":21991921,"url":"https://github.com/elct9620/rails-letsencrypt","last_synced_at":"2025-10-22T21:50:38.185Z","repository":{"id":45644360,"uuid":"90434165","full_name":"elct9620/rails-letsencrypt","owner":"elct9620","description":"The Let's Encrypt certificate manager for rails","archived":false,"fork":false,"pushed_at":"2025-10-07T18:13:17.000Z","size":350,"stargazers_count":132,"open_issues_count":7,"forks_count":40,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-10-07T20:27:30.294Z","etag":null,"topics":["letsencrypt","rails","ruby","setup-ssl"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elct9620.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-05-06T03:17:08.000Z","updated_at":"2025-10-07T18:13:21.000Z","dependencies_parsed_at":"2024-06-21T18:56:51.302Z","dependency_job_id":"af0fa792-dd3c-442a-9a44-ec12580d906a","html_url":"https://github.com/elct9620/rails-letsencrypt","commit_stats":{"total_commits":85,"total_committers":7,"mean_commits":"12.142857142857142","dds":"0.21176470588235297","last_synced_commit":"14278e44f52f866b2a1fc79c7b6bc2b9f765b7e8"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/elct9620/rails-letsencrypt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elct9620%2Frails-letsencrypt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elct9620%2Frails-letsencrypt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elct9620%2Frails-letsencrypt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elct9620%2Frails-letsencrypt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elct9620","download_url":"https://codeload.github.com/elct9620/rails-letsencrypt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elct9620%2Frails-letsencrypt/sbom","scorecard":{"id":371550,"data":{"date":"2025-08-11","repo":{"name":"github.com/elct9620/rails-letsencrypt","commit":"73295409ec2f931b5e6221af9fc4e3a19f436b70"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.8,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/24 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: topLevel 'contents' permission set to 'write': .github/workflows/dependabot-prs.yml:7","Warn: no topLevel permission defined: .github/workflows/main.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/dependabot-prs.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/elct9620/rails-letsencrypt/dependabot-prs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yaml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/elct9620/rails-letsencrypt/main.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yaml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/elct9620/rails-letsencrypt/main.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yaml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/elct9620/rails-letsencrypt/main.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yaml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/elct9620/rails-letsencrypt/main.yaml/main?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 6 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T13:06:46.529Z","repository_id":45644360,"created_at":"2025-08-18T13:06:46.529Z","updated_at":"2025-08-18T13:06:46.529Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280520818,"owners_count":26344438,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-22T02:00:06.515Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["letsencrypt","rails","ruby","setup-ssl"],"created_at":"2024-11-29T20:12:10.644Z","updated_at":"2025-10-22T21:50:38.169Z","avatar_url":"https://github.com/elct9620.png","language":"Ruby","readme":"Rails LetsEncrypt\n===\n\n[![Gem Version](https://badge.fury.io/rb/rails-letsencrypt.svg)](https://badge.fury.io/rb/rails-letsencrypt)\n[![Code Climate](https://codeclimate.com/github/elct9620/rails-letsencrypt/badges/gpa.svg)](https://codeclimate.com/github/elct9620/rails-letsencrypt)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/elct9620/rails-letsencrypt)\n\nProvide manageable Let's Encrypt Certificate for Rails.\n\n## Requirement\n\n* Rails 7.2+\n* Ruby 3.2+\n\n## Installation\n\nPuts this in your Gemfile:\n\n```ruby\ngem 'rails-letsencrypt'\n```\n\nRun install migrations\n\n```bash\nrails generate lets_encrypt:install\nrake db:migrate\n```\n\nSetup private key for Let's Encrypt API, and create an account at letsencrypt.org associated with that key\n\n```bash\nrails generate lets_encrypt:register\n```\n\n\nAdd `acme-challenge` mounts in `config/routes.rb`\n```ruby\nmount LetsEncrypt::Engine =\u003e '/.well-known'\n```\n\n### Configuration\n\nAdd a file to `config/initializers/letsencrypt.rb` and put below config you need.\n\n```ruby\nLetsEncrypt.config do |config|\n  # Configure the ACME server\n  # Default is Let's Encrypt production server\n  # config.acme_server = 'https://acme-v02.api.letsencrypt.org/directory'\n\n  # Using Let's Encrypt staging server or not\n  # Default only `Rails.env.production? == true` will use Let's Encrypt production server.\n  # config.use_staging = true\n\n  # Set the private key path\n  # Default is locate at config/letsencrypt.key\n  config.private_key_path = Rails.root.join('config', 'letsencrypt.key')\n\n  # Use environment variable to set private key\n  # If enable, the API Client will use `LETSENCRYPT_PRIVATE_KEY` as private key\n  # Default is false\n  config.use_env_key = false\n\n  # Should sync certificate into redis\n  # When using ngx_mruby to dynamic load certificate, this will be helpful\n  # Default is false\n  config.save_to_redis = false\n\n  # The redis server url\n  # Default is nil\n  config.redis_url = 'redis://localhost:6379/1'\n\n  # Enable it if you want to customize the model\n  # Default is LetsEncrypt::Certificate\n  # config.certificate_model = 'MyCertificate'\n\n  # Configure the maximum attempts to re-check status when verifying or issuing\n  # config.max_attempts = 30\n\n  # Configure the interval between attempts\n  # config.retry_interval = 1\nend\n```\n\n\u003e [!WARNING]\n\u003e **Depcrecation Notice**\n\u003e The `use_staging` will be removed in the future, and the `acme_server` will be used to determine the server.\n\n## Usage\n\nThe SSL certificate setup depends on the web server, this gem can work with `ngx_mruby` or `kong`.\n\n### Service\n\n#### Renew Service\n\n```ruby\ncertificate = LetsEncrypt::Certificate.find_by(domain: 'example.com')\n\nservice = LetsEncrypt::RenewService.new\nservice.execute(certificate)\n```\n\n#### Verify Service\n\n```ruby\ncertificate = LetsEncrypt::Certificate.find_by(domain: 'example.com')\n\norder = LetsEncrypt.client.new_order(identifiers: [certificate.domain])\n\nservice = LetsEncrypt::VerifyService.new\nservice.execute(certificate, order)\n```\n\n#### Issue Service\n\n```ruby\ncertificate = LetsEncrypt::Certificate.find_by(domain: 'example.com')\n\norder = LetsEncrypt.client.new_order(identifiers: [certificate.domain])\n\nservice = LetsEncrypt::IssueService.new\nservice.execute(certificate, order)\n```\n\n### Certificate Model\n\n#### Create\n\nAdd a new domain into the database.\n\n```ruby\ncert = LetsEncrypt::Certificate.create(domain: 'example.com')\ncert.get # alias  `verify \u0026\u0026 issue`\n```\n\n\u003e [!WARNING]\n\u003e **Depcrecation Notice**\n\u003e The `get` will be replaced by `RenewService` in the future.\n\n#### Verify\n\nMakes a request to Let's Encrypt and verify domain\n\n```ruby\ncert = LetsEncrypt::Certificate.find_by(domain: 'example.com')\ncert.verify\n```\n\n\u003e [!WARNING]\n\u003e **Depcrecation Notice**\n\u003e The `verify` will be replaced by `VerifyService` in the future.\n\n#### Issue\n\nAsk Let's Encrypt to issue a new certificate.\n\n```ruby\ncert = LetsEncrypt::Certificate.find_by(domain: 'example.com')\ncert.issue\n```\n\n\u003e [!WARNING]\n\u003e **Depcrecation Notice**\n\u003e The `issue` will be replaced by `IssueService` in the future.\n\n#### Renew\n\n```ruby\ncert = LetsEncrypt::Certificate.find_by(domain: 'example.com')\ncert.renew\n```\n\n\u003e [!WARNING]\n\u003e **Depcrecation Notice**\n\u003e The `renew` will be replaced by `RenewService` in the future.\n\n#### Status\n\nCheck a certificate is verified and issued.\n\n```ruby\ncert = LetsEncrypt::Certificate.find_by(domain: 'example.com')\ncert.active? # =\u003e true\n```\n\nCheck a certificate is expired.\n\n```ruby\ncert = LetsEncrypt::Certificate.find_by(domain: 'example.com')\ncert.expired? # =\u003e false\n```\n\n### Tasks\n\nTo renew a certificate, you can run `renew` task to renew coming expires certificates.\n\n```bash\nrake letsencrypt:renew\n```\n\n### Jobs\n\nIf you are using Sidekiq or others, you can enqueue renew task daily.\n\n```ruby\nLetsEncrypt::RenewCertificatesJob.perform_later\n```\n\n### Subscribe\n\nWhen the certificate is trying to issue a new one, you can subscribe it for logging or error handling.\n\n```ruby\nActiveSupport::Notifications.subscribe('letsencrypt.renew') do |name, start, finish, id, payload|\n  Rails.logger.info(\"Certificate for #{payload[:domain]} is renewed\")\nend\n```\n\nThe available events are:\n\n* `letsencrypt.renew`\n* `letsencrypt.verify`\n* `letsencrypt.issue`\n\n### ngx_mruby\n\nThe setup is following this [Article](http://hb.matsumoto-r.jp/entry/2017/03/23/173236)\n\nAdd `config/initializers/letsencrypt.rb` to add config to sync certificate.\n\n```ruby\nLetsEncrypt.config do |config|\n  config.redis_url = 'redis://localhost:6379/1'\n  config.save_to_redis = true\nend\n```\n\nConnect `Redis` when Nginx worker start\n```\nhttp {\n  # ...\n  mruby_init_worker_code '\n    userdata = Userdata.new\n    userdata.redis = Redis.new \"127.0.0.1\", 6379\n    # If your redis database is not 0, please select a correct one\n    userdata.redis.select 1\n  ';\n}\n```\n\nSetup SSL using mruby\n```\nserver {\n  listen 443 ssl;\n  server_name _;\n\n  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;\n  ssl_ciphers HIGH:!aNULL:!MD5;\n  ssl_certificate certs/dummy.crt;\n  ssl_certificate_key certs/dummy.key;\n\n  mruby_ssl_handshake_handler_code '\n    ssl = Nginx::SSL.new\n    domain = ssl.servername\n\n    redis = Userdata.new.redis\n    unless redis[\"#{domain}.crt\"].nil? and redis[\"#{domain}.key\"].nil?\n      ssl.certificate_data = redis[\"#{domain}.crt\"]\n      ssl.certificate_key_data = redis[\"#{domain}.key\"]\n    end\n  ';\n}\n```\n\n## License\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felct9620%2Frails-letsencrypt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felct9620%2Frails-letsencrypt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felct9620%2Frails-letsencrypt/lists"}