# HG changeset patch
# User Ian Baum <ibaum@gitlab.com>
# Date 1518626913 0
#      Wed Feb 14 16:48:33 2018 +0000
# Node ID c6afc63063776c876d0c0836ee9cc18a422e0ec4
# Parent  5541b5ea03314823da9da65449c6474089052d70
Add le renew

diff --git a/doc/settings/ssl.md b/doc/settings/ssl.md
--- a/doc/settings/ssl.md
+++ b/doc/settings/ssl.md
@@ -59,9 +59,19 @@
 
 ### Renewing
 
-By default, when `gitlab-ctl reconfigure` is run, if the certificate is within 30 days of expiring, it will automatically be renewed.
+There are two commands that can be used to renew your Let's Encrypt certificates.
+
+1. `gitlab-ctl reconfigure`
+1. `gitlab-ctl renew-le-certs`
+
+Both commands require root privileges and will only perform a request to Let's Encrypt if the certificates are close to expiration date. Please consider [LE rate limits](https://letsencrypt.org/docs/rate-limits/) if you get an error during renewal.
 
-Both tools will only perform a request to Let's Encrypt if the certificates are near expiration, so you don't need to be concerned about hitting any [rate limits](https://letsencrypt.org/docs/rate-limits/).
+It is recommended to setup a scheduled task to run `gitlab-ctl le-renew-certs` to ensure your Let's Encrypt certificates stay up to date automatically.
+
+An example cron entry to check daily
+```sh
+0 0 * * * /opt/gitlab/bin/gitlab-ctl le-renew-certs > /dev/null
+```
 
 ## Troubleshooting
 
diff --git a/files/gitlab-cookbooks/gitlab/recipes/letsencrypt_renew.rb b/files/gitlab-cookbooks/gitlab/recipes/letsencrypt_renew.rb
new file mode 100644
--- /dev/null
+++ b/files/gitlab-cookbooks/gitlab/recipes/letsencrypt_renew.rb
@@ -0,0 +1,21 @@
+#
+# Copyright:: Copyright (c) 2018 GitLab Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe 'gitlab::config'
+
+if node['gitlab']['nginx']['enable'] && node['letsencrypt']['enable']
+  include_recipe 'letsencrypt::enable'
+end
diff --git a/files/gitlab-cookbooks/renew-letsencrypt.json b/files/gitlab-cookbooks/renew-letsencrypt.json
new file mode 100644
--- /dev/null
+++ b/files/gitlab-cookbooks/renew-letsencrypt.json
@@ -0,0 +1,5 @@
+{
+  "run_list": [
+      "recipe[gitlab::letsencrypt_renew]"
+  ]
+}
diff --git a/files/gitlab-ctl-commands/letsencrypt.rb b/files/gitlab-ctl-commands/letsencrypt.rb
new file mode 100644
--- /dev/null
+++ b/files/gitlab-ctl-commands/letsencrypt.rb
@@ -0,0 +1,23 @@
+#
+# Copyright:: Copyright (c) 2018 GitLab Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "#{base_path}/embedded/service/omnibus-ctl/lib/gitlab_ctl"
+
+add_command_under_category('renew-le-certs', "Let's Encrypt", "Renew the existing Let's Encrypt certificates", 2) do
+  status = GitlabCtl::Util.chef_run('solo.rb', 'renew-letsencrypt.json')
+  $stdout.puts status.stdout
+  $stderr.puts Rainbow("There was an error renewing Let's Encrypt certificates, please checkout the output").red if status.error?
+end
diff --git a/files/gitlab-ctl-commands/lib/gitlab_ctl/util.rb b/files/gitlab-ctl-commands/lib/gitlab_ctl/util.rb
--- a/files/gitlab-ctl-commands/lib/gitlab_ctl/util.rb
+++ b/files/gitlab-ctl-commands/lib/gitlab_ctl/util.rb
@@ -69,6 +69,11 @@
       def userinfo(username)
         Etc.getpwnam(username)
       end
+
+      def chef_run(config, attribs)
+        cookbook_path = "/opt/gitlab/embedded/cookbooks"
+        run_command("/opt/gitlab/embedded/bin/chef-client -z -c #{cookbook_path}/#{config} -j #{cookbook_path}/#{attribs}")
+      end
     end
   end
 end
diff --git a/spec/chef/recipes/letsencrypt_spec.rb b/spec/chef/recipes/letsencrypt_spec.rb
--- a/spec/chef/recipes/letsencrypt_spec.rb
+++ b/spec/chef/recipes/letsencrypt_spec.rb
@@ -99,19 +99,19 @@
 end
 
 # This should work standalone for renewal purposes
-describe 'letsencrypt::enable' do
+describe 'letsencrypt::renew' do
   let(:chef_run) do
-    ChefSpec::SoloRunner.new do |node|
-      node.normal['gitlab']['external-url'] = 'https://standalone.fakehost.com'
-      node.normal['gitlab']['nginx']['log_directory'] = '/fake/dir'
-      node.normal['gitlab']['nginx']['ssl_certificate'] = '/fake/path/cert.crt'
-      node.normal['gitlab']['nginx']['ssl_certificate_key'] = '/fake/path/cert.key'
-      node.normal['gitlab']['logging'] = {}
-    end.converge('letsencrypt::enable')
+    ChefSpec::SoloRunner.converge('gitlab::letsencrypt_renew')
   end
 
   before do
     allow(Gitlab).to receive(:[]).and_call_original
+    stub_gitlab_rb(
+      external_url: 'https://standalone.fakehost.com',
+      letsencrypt: {
+        enable: true
+      }
+    )
   end
 
   it 'executes letsencrypt_certificate' do