From dbfd2e0677afaa1f13ab4645d8759353b79dce35 Mon Sep 17 00:00:00 2001 From: Bohung Date: Wed, 11 Aug 2021 16:16:14 +0800 Subject: [PATCH] Add certbot feature to install cert. --- .../admin/site_panel_controller.rb | 22 ++++- app/models/site_cert.rb | 1 + app/models/site_server.rb | 1 + .../site_panel/_server_manager_index.html.erb | 39 +++++++- .../site_panel/edit_server_info.html.erb | 8 ++ .../site_panel/get_certs_for_site.html.erb | 28 ++++++ config/locales/en.yml | 3 + config/locales/zh_tw.yml | 3 + config/routes.rb | 3 + lib/tasks/change_site_cert.rake | 94 +++++++++++++++---- lib/tasks/detect_sites.rake | 21 ++++- lib/tasks/exec_command.rake | 33 +++++-- lib/tasks/install_certbot.rake | 83 ++++++++++++++++ 13 files changed, 303 insertions(+), 36 deletions(-) create mode 100644 lib/tasks/install_certbot.rake diff --git a/app/controllers/admin/site_panel_controller.rb b/app/controllers/admin/site_panel_controller.rb index ebefd4a..a727e22 100644 --- a/app/controllers/admin/site_panel_controller.rb +++ b/app/controllers/admin/site_panel_controller.rb @@ -39,7 +39,7 @@ class Admin::SitePanelController < OrbitAdminController domain_name_search_text = "" end @site_certs = SiteCert.all.where(:is_valid=>true,:domain_names=>/\A#{domain_name_search_text}/) - @site_certs = SiteCert.all + # @site_certs = SiteCert.all if site_construct @enable_cert_id = site_construct.site_cert_id end @@ -129,11 +129,21 @@ class Admin::SitePanelController < OrbitAdminController render :json => thread.status end elsif params[:type] == 'get_server_names' - render :json => (SiteServer.all.map{|s| s.server_name rescue ""}.select{|n| !n.blank?} rescue []) + render :json => (SiteServer.all.where(:active=>true).map{|s| s.server_name rescue ""}.select{|n| !n.blank?} rescue []) else @site_server = SiteServer.find(params[:id]) end end + def install_certbot + extra_text = "" + if params[:server_name].present? + extra_text = "[#{params[:server_name].gsub(/[\(\)\[\]]/){|ff| "\\"+ff }}]" + end + Thread.new do + system("bundle exec rake create_site:install_certbot#{extra_text}") + end + render :json => {"success"=>true} + end def create server_ability = ServerAbility.first if server_ability.available @@ -227,9 +237,13 @@ class Admin::SitePanelController < OrbitAdminController elsif params[:type] == 'select_cert' @site_construct = SiteConstruct.find(params[:id]) @site_construct.update(:redirect_to_https=>params[:redirect_to_https]) - @site_construct.update(:site_cert_id=>BSON::ObjectId(params[:site_cert_id])) + is_certbot = true + if params[:site_cert_id] != "certbot" + is_certbot = false + @site_construct.update(:site_cert_id=>BSON::ObjectId(params[:site_cert_id])) + end Thread.new do - system("bundle exec rake create_site:change_site_cert[#{params[:id]}]") + system("bundle exec rake create_site:change_site_cert[#{params[:id]},#{is_certbot}]") end else Thread.new do diff --git a/app/models/site_cert.rb b/app/models/site_cert.rb index 56672e5..5cbb407 100644 --- a/app/models/site_cert.rb +++ b/app/models/site_cert.rb @@ -4,6 +4,7 @@ class SiteCert mount_uploader :cert_file, AssetUploader #Public key mount_uploader :ca_bundle, AssetUploader mount_uploader :private_key, AssetUploader + field :is_certbot, type: Boolean ,default: false field :is_valid , type: Boolean ,default: false field :domain_names , type: Array ,default: [] field :source_paths , type: Array ,default: [] diff --git a/app/models/site_server.rb b/app/models/site_server.rb index 6e1afd7..0fb31d1 100644 --- a/app/models/site_server.rb +++ b/app/models/site_server.rb @@ -11,6 +11,7 @@ class SiteServer field :account , type: String ,default: '' field :password , type: String ,default: '' field :active , type: Boolean ,default: true + field :has_certbot, type: Boolean , default: false def domain_names if self.domain_name != '' [self.domain_name] diff --git a/app/views/admin/site_panel/_server_manager_index.html.erb b/app/views/admin/site_panel/_server_manager_index.html.erb index b313df4..6fc86ff 100644 --- a/app/views/admin/site_panel/_server_manager_index.html.erb +++ b/app/views/admin/site_panel/_server_manager_index.html.erb @@ -1,9 +1,25 @@ + + @@ -19,8 +35,18 @@ Development: <%=SiteConstruct.where(:hidden.ne=> true,:server_type => site_server.server_name,:rails_env.in=>["development",nil],:status=>"finish").count %>

- + +
Sites amount Server name IPCertbot Action
<%=site_server.server_name%><%=site_server.server_name%><%= 'X'.html_safe if !(site_server.active) %> <%=site_server.ip%> + <% if site_server.has_certbot%> + <%= t("client_management.alreay_install") %> + <% else %> + <%= t("client_management.not_install") %> + <% if site_server.active %> + Install certbot + <% end %> + <% end %> + "><%=t(:edit)%> ';}"><%=t(:remove)%> @@ -95,6 +121,9 @@ var status_text = "not yet create"; else var status_text = status_relation[status]; + if(!status_text){ + status_text = ""+status+""; + } $("#info_texts").html(status_text+"
"+infos.join("
")); msg_end.scrollIntoView(); timeout_id = window.setTimeout(see_infos(key),1000); @@ -156,5 +185,13 @@ show_infos_dialog(key); }) }); + $(".install_certbot").off("click").on("click",function(){ + var server_name = $(this).data("name"); + if( server_name == undefined) + server_name = ""; + $.post("<%=admin_site_panel_install_certbot_path%>",{"server_name":server_name}).done(function(){ + show_infos_dialog("install_certbot"); + }) + }) }) \ No newline at end of file diff --git a/app/views/admin/site_panel/edit_server_info.html.erb b/app/views/admin/site_panel/edit_server_info.html.erb index 7c8a715..e2606ba 100644 --- a/app/views/admin/site_panel/edit_server_info.html.erb +++ b/app/views/admin/site_panel/edit_server_info.html.erb @@ -49,6 +49,14 @@ <%= select_tags(f, @module_app) %> + <% unless @site_server.new_record? %> +
+ +
+ <%= f.check_box :active %> +
+
+ <% end %>
diff --git a/app/views/admin/site_panel/get_certs_for_site.html.erb b/app/views/admin/site_panel/get_certs_for_site.html.erb index d84ef4d..b3deb19 100644 --- a/app/views/admin/site_panel/get_certs_for_site.html.erb +++ b/app/views/admin/site_panel/get_certs_for_site.html.erb @@ -1,4 +1,32 @@ <% if @site_certs.count == 0 %> + <% site_server = @site_construct.site_server %> + <% if (site_server.has_certbot rescue false)%> +
+ +
+ + + + + + + + + + + + + + + +
<%=t('client_management.upload_date')%><%=t('client_management.start_date')%>/<%=t('client_management.end_date')%><%=t('client_management.domain_name')%>
<%=radio_button_tag("site_cert","certbot",false)%>Certbot
+ <% else %> + Please install certbot first! +
+ <% end %> <%= link_to t('client_management.upload_cert'),upload_cert_admin_site_panel_index_path, :target=>"_blank" %> <% else %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 3acf44e..782538d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -7,6 +7,9 @@ en: upload_cert: Upload Cert cert_management: Cert Management client_management: + alreay_install: Alreay install + not_install: Not install + active: Active over_the_limit: Please Contact us (RulingCare) to add the limit of Site number. redirect_to_https: Redirect to https start_date: Start Date diff --git a/config/locales/zh_tw.yml b/config/locales/zh_tw.yml index be82e1f..92a4290 100644 --- a/config/locales/zh_tw.yml +++ b/config/locales/zh_tw.yml @@ -7,6 +7,9 @@ zh_tw: upload_cert: 上傳憑證 cert_management: 憑證管理 client_management: + alreay_install: 已安裝 + not_install: 未安裝 + active: 啟用 over_the_limit: 請您聯絡客服以增加可以新增的網站數量上限。 redirect_to_https: 跳轉到https start_date: 開始日期 diff --git a/config/routes.rb b/config/routes.rb index 0f53110..b3bc57f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -48,6 +48,9 @@ Rails.application.routes.draw do get "site_panel/server_manager" => "site_panel#server_manager" get "site_panel/edit_server_info" => "site_panel#edit_server_info" post "site_panel/edit_server_info" => "site_panel#edit_server_info" + get "site_panel/install_certbot" => "site_panel#install_certbot" + post "site_panel/install_certbot" => "site_panel#install_certbot" + post "site_panel/update_cert_setting" => "site_panel#update_cert_setting" resources :site_panel do delete 'destroy_cert' diff --git a/lib/tasks/change_site_cert.rake b/lib/tasks/change_site_cert.rake index e06b86b..90e1c8f 100644 --- a/lib/tasks/change_site_cert.rake +++ b/lib/tasks/change_site_cert.rake @@ -3,33 +3,87 @@ require 'pathname' require 'json' namespace :create_site do desc "Change Site Cert" - task :change_site_cert,[:id] => :environment do |task,args| + task :change_site_cert,[:id,:is_certbot] => :environment do |task,args| begin @site_construct = SiteConstruct.find(args.id) @site_cert = @site_construct.site_cert site_server = @site_construct.site_server @site_construct.update(:infos=>[],:status=>"changing") - if !site_server.nil? && !@site_cert.nil? + is_certbot = (args.is_certbot == "true") || (@site_cert.is_certbot rescue false) + if !site_server.nil? && (!@site_cert.nil? || is_certbot) @password = site_server.password Net::SSH.start(site_server.ip , site_server.account , password: site_server.password) do |ssh| - update_infos("Copying Cert to #{@site_construct.server_type}...") - cert_file_content = [(@site_cert.cert_file.file.read.strip rescue ""),(@site_cert.ca_bundle.file.read.strip rescue "")].join("\n").strip - private_key_content = @site_cert.private_key.file.read - cert_file_store_path = @site_construct.cert_file_remote_store_path - exec_ssh_command_by_sudo(ssh,"mkdir -p #{File.dirname(cert_file_store_path)}") - exec_command_by_user(ssh,"x='#{cert_file_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{cert_file_store_path}\"") - private_key_store_path = @site_construct.private_key_remote_store_path - exec_ssh_command_by_sudo(ssh,"mkdir -p #{File.dirname(private_key_store_path)}") - exec_command_by_user(ssh,"x='#{private_key_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{private_key_store_path}\"") - update_infos("Finish copy.") - update_infos("Setting Cert...") - nginx_file_content = exec_command_by_user(ssh,"cat #{@site_construct.nginx_file}") - all_ports = (@site_construct.port + ["443"]).uniq - @site_construct.update(:port=> all_ports ) - nginx_file_content = @site_construct.generate_nginx_text(nginx_file_content) - cmd = "x='#{nginx_file_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{@site_construct.nginx_file}\"" - exec_command_by_user(ssh,cmd) - puts nginx_file_content + if is_certbot + domain_name = @site_construct.domain_name + if domain_name.present? + certbot_path = exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'which certbot'",false,true).strip + if certbot_path.present? + if @site_cert + update_infos("Using certbot to change cert setting...") + else + update_infos("Using certbot to generate cert for #{domain_name}...") + end + redirect_to_https = @site_construct.redirect_to_https + exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' #{certbot_path} --nginx -d #{domain_name} -n --#{redirect_to_https ? 'redirect' : 'no-redirect'}",true,false) + nginx_file = @site_construct.nginx_file + nginx_file_content = exec_ssh_command_by_sudo_and_see_output(ssh,"cat #{nginx_file}",false,true) + crt_file_path = nginx_file_content.match(/ssl_certificate\s+(.*)/)[1].split(';').first rescue '' + private_key_path = nginx_file_content.match(/ssl_certificate_key\s+(.*)/)[1].split(';').first rescue '' + site_cert = @site_construct.site_cert + if crt_file_path.present? && private_key_path.present? + if site_cert.nil? + site_cert = SiteCert.where(:source_paths=>[crt_file_path,private_key_path]).first + site_cert = SiteCert.new if site_cert.nil? + end + if true #site_cert.source_paths.count == 0 + site_cert["cert_file"] = File.basename(crt_file_path) + cert_file_store_path = site_cert.cert_file.file.file + crt_file_content = exec_ssh_command_by_sudo_and_see_output(ssh,"cat #{crt_file_path}",false).select{|s| s.present?}.join("\n").strip.split(/(\r\n|\n)/).select{|s| s.present?}.join("\n") + FileUtils.mkdir_p(File.dirname(cert_file_store_path)) unless Dir.exist?(File.dirname(cert_file_store_path)) + File.open(site_cert.cert_file.file.file,'w+'){|f| f.write(crt_file_content)} + site_cert["private_key"] = File.basename(private_key_path) + private_key_store_path = site_cert.private_key.file.file + private_key_content = exec_ssh_command_by_sudo_and_see_output(ssh,"cat #{private_key_path}",false).select{|s| s.present?}.join("\n").strip.split(/(\r\n|\n)/).select{|s| s.present?}.join("\n") + FileUtils.mkdir_p(File.dirname(private_key_store_path)) unless Dir.exist?(File.dirname(private_key_path)) + File.open(site_cert.private_key.file.file,'w+'){|f| f.write(private_key_content)} + site_cert.source_paths = [crt_file_path,private_key_path] + site_cert.is_certbot = private_key_path.include?("letsencrypt") + site_cert.save + @site_construct.update(:site_cert=>site_cert) + end + all_ports = (@site_construct.port + ["443"]).uniq + @site_construct.update(:port=> all_ports ) + update_infos("Finish installing cert with certbot!") + else + update_infos("Certbot generate cert failed!") + update_infos("Please check your domain dns setting(A record)!") + @site_construct.update(:status=>"error") + end + else + update_infos("Please install certbot first!") + end + else + update_infos("Please set domain name first!") + end + else + update_infos("Copying Cert to #{@site_construct.server_type}...") + cert_file_content = [(@site_cert.cert_file.file.read.strip rescue ""),(@site_cert.ca_bundle.file.read.strip rescue "")].join("\n").strip + private_key_content = @site_cert.private_key.file.read + cert_file_store_path = @site_construct.cert_file_remote_store_path + exec_ssh_command_by_sudo(ssh,"mkdir -p #{File.dirname(cert_file_store_path)}") + exec_command_by_user(ssh,"x='#{cert_file_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{cert_file_store_path}\"") + private_key_store_path = @site_construct.private_key_remote_store_path + exec_ssh_command_by_sudo(ssh,"mkdir -p #{File.dirname(private_key_store_path)}") + exec_command_by_user(ssh,"x='#{private_key_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{private_key_store_path}\"") + update_infos("Finish copy.") + update_infos("Setting Cert...") + nginx_file_content = exec_command_by_user(ssh,"cat #{@site_construct.nginx_file}") + all_ports = (@site_construct.port + ["443"]).uniq + @site_construct.update(:port=> all_ports ) + nginx_file_content = @site_construct.generate_nginx_text(nginx_file_content) + cmd = "x='#{nginx_file_content}'; echo '#{@password}' | sudo -S sh -c \"echo '$x' > #{@site_construct.nginx_file}\"" + exec_command_by_user(ssh,cmd) + end exec_ssh_command_by_sudo(ssh,"service nginx restart") update_infos("Finish!") @site_construct.update(:status=>"finish") diff --git a/lib/tasks/detect_sites.rake b/lib/tasks/detect_sites.rake index 4acb264..75c8a58 100644 --- a/lib/tasks/detect_sites.rake +++ b/lib/tasks/detect_sites.rake @@ -8,11 +8,12 @@ namespace :create_site do Multithread.where(:key=>'detect_sites').each{|thread| thread.destroy if (thread.status["status"] == "error" || thread.status["status"] == "finish")} Multithread.where(:key=>'detect_sites').destroy @thread = Multithread.where(:key=>'detect_sites').first + @type = "exec_all" if @thread.nil? begin @thread = Multithread.create(:key=>'detect_sites',:status=>{"infos"=>[],"status"=>"detecting"}) if( args.detect_name.nil? rescue true) - site_servers = SiteServer.all.to_a + site_servers = SiteServer.all.where(:active=>true).to_a else site_servers = SiteServer.where(:server_name=>args.detect_name).to_a end @@ -33,6 +34,20 @@ namespace :create_site do next end Net::SSH.start(@site_server.ip , @site_server.account , password: @site_server.password) do |ssh| + certbot_path = exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'which certbot'",false,true).strip + @site_server.has_certbot = certbot_path.present? + @site_server.save + if @site_server.has_certbot + update_thread_infos("Checking certbot renew cronjob...") + crontab_lines = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' crontab -l",false,false) + certbot_renew_command = crontab_lines.select{|l| l.include?("certbot") && l.include?("renew")}[0] + unless certbot_renew_command + update_thread_infos("Add certbot renew cronjob!") + certbot_renew_command = "30 2 * * 1 #{certbot_path} renew --no-self-upgrade --post-hook 'sudo service nginx restart' > /var/log/le-renew.log" + update_thread_infos(certbot_renew_command) + exec_ssh_command_by_sudo_and_see_output(ssh,"CRON=\"#{certbot_renew_command}\" && (sudo -p 'sudo password:' crontab -l; echo \"\$CRON\" ) | sudo -p 'sudo password:' crontab -",false) + end + end nginx_include_dir = exec_command_by_user(ssh,'grep include /etc/nginx/nginx.conf | grep -v "\#\|include /etc/nginx/mime.types\|include /etc/nginx/conf.d/\*.conf\|/etc/nginx/sites-enabled/\*"') nginx_include_dir = nginx_include_dir.gsub(/include|;|\n/,'').strip domain_name = @site_server.domain_name#'serv.rulingcom.com' @@ -49,8 +64,7 @@ namespace :create_site do server_name_list << server_name_for_site end server_name = server_name_list.join(' ') - nginx_file_content = exec_ssh_command_by_sudo_and_see_output(ssh,"cat #{nginx_file}",false) - nginx_file_content = nginx_file_content.join('\n') if nginx_file_content.class == Array + nginx_file_content = exec_ssh_command_by_sudo_and_see_output(ssh,"cat #{nginx_file}",false,true) site_path = Pathname.new(exec_ssh_command_by_sudo(ssh,"echo `grep root #{nginx_file} | grep -v -e '#.*root'`").to_s.split("\n").first.to_s.strip.split("root").last.to_s.gsub(";","").strip).dirname.to_s if site_path.present? && exec_ssh_command_by_sudo(ssh,"ls #{site_path}").split.length != 0 && exec_ssh_command_by_sudo(ssh,"ls #{site_path}/Gemfile").include?("No such file or directory") SiteConstruct.where(:server_type => @site_server.server_name , :domain_name=>server_name).destroy @@ -128,6 +142,7 @@ namespace :create_site do FileUtils.mkdir_p(File.dirname(private_key_store_path)) unless Dir.exist?(File.dirname(private_key_path)) File.open(site_cert.private_key.file.file,'w+'){|f| f.write(private_key_content)} site_cert.source_paths = [crt_file_path,private_key_path] + site_cert.is_certbot = private_key_path.include?("letsencrypt") site_cert.save site_construct.update(:site_cert=>site_cert) end diff --git a/lib/tasks/exec_command.rake b/lib/tasks/exec_command.rake index ee7217d..3326a98 100644 --- a/lib/tasks/exec_command.rake +++ b/lib/tasks/exec_command.rake @@ -120,6 +120,7 @@ namespace :exec_commands do return output end def update_infos_for_exec(info,update_last=false) + return if @site_construct.nil? if update_last && !@site_construct.infos.empty? @site_construct.infos[-1] += info.to_s else @@ -137,12 +138,16 @@ namespace :exec_commands do @thread.save! return @thread.status["infos"] end - def exec_ssh_command_and_see_output(session,command,update=true) + def exec_ssh_command_and_see_output(session,command,update=true,output_string=false) outputs = [] @flag = (@type == "exec_all") if update - update_thread_infos_for_exec("execing #{command} on on #{@site_construct.domain_name}") if @flag - update_infos_for_exec("execing #{command}") + if @site_construct + update_thread_infos_for_exec("execing #{command} on on #{@site_construct.domain_name}") if @flag + update_infos_for_exec("execing #{command}") + elsif @thread + update_thread_infos_for_exec("execing #{command}...") + end end session.open_channel do |channel| channel.request_pty do |channel, success| @@ -173,21 +178,33 @@ namespace :exec_commands do end channel.on_close do |ch| if update - update_thread_infos_for_exec("finish execing #{command} on #{@site_construct.domain_name}") if @flag - update_infos_for_exec("finish execing #{command}") + if @site_construct + update_thread_infos_for_exec("finish execing #{command} on #{@site_construct.domain_name}") if @flag + update_infos_for_exec("finish execing #{command}") + elsif @thread + update_thread_infos_for_exec("finish execing #{command}") + end end end end end end session.loop - return outputs + if output_string + return outputs.join("\n") + else + return outputs + end end - def exec_ssh_command_by_sudo_and_see_output(session,command,update=true) + def exec_ssh_command_by_sudo_and_see_output(session,command,update=true,output_string=false) outputs = exec_ssh_command_and_see_output(session,command,update) if outputs.join("\n").include?("Permission denied") || outputs.join("\n").include?("Operation not permitted") outputs = exec_ssh_command_and_see_output(session,"sudo -p 'sudo password:' #{command}",update) end - return outputs + if output_string + return outputs.join("\n") + else + return outputs + end end end \ No newline at end of file diff --git a/lib/tasks/install_certbot.rake b/lib/tasks/install_certbot.rake new file mode 100644 index 0000000..b21948b --- /dev/null +++ b/lib/tasks/install_certbot.rake @@ -0,0 +1,83 @@ +require 'net/ssh' +require 'pathname' +require 'fileutils' +namespace :create_site do + desc "Install certbot" + task :install_certbot,[:server_name] => :environment do |task,args| + #Multithread.where(:key=>'detect_sites').destroy + Multithread.where(:key=>'install_certbot').each{|thread| thread.destroy if (thread.status["status"] == "error" || thread.status["status"] == "finish")} + Multithread.where(:key=>'install_certbot').destroy + @thread = Multithread.where(:key=>'install_certbot').first + @type = "exec_all" + if @thread.nil? + begin + @thread = Multithread.create(:key=>'install_certbot',:status=>{"infos"=>[],"status"=>"running"}) + if( args.server_name.nil? rescue true) + site_servers = SiteServer.all.where(:active=>true).to_a + else + site_servers = SiteServer.where(:server_name=>args.server_name).to_a + end + site_servers.each do |site_server| + @site_server = site_server + update_thread_infos(""+@site_server.server_name+"") + @password = @site_server.password + begin + begin + Net::SSH.start(@site_server.ip , @site_server.account , password: @site_server.password) do |ssh| + end + rescue Net::SSH::HostKeyMismatch + system("ssh-keygen -f \"$HOME/.ssh/known_hosts\" -R #{@site_server.ip}") + rescue Errno::ENOTTY + system("ssh-add \"$HOME/.ssh/id_rsa\"") + rescue => e + update_thread_infos(e.to_s) + next + end + Net::SSH.start(@site_server.ip , @site_server.account , password: @site_server.password) do |ssh| + certbot_path = exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'which certbot'",false,true).strip + snap_path = exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'which snap'",false,true).strip + if certbot_path.blank? + if snap_path.blank? + update_thread_infos("Installing snap...") + exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' apt update",true,false) + exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' apt install snapd -y",true,false) + snap_path = exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'which snap'",false,true).strip + end + if snap_path.present? + update_thread_infos("Installing snap core...") + exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' bash -l -c 'snap install core && snap refresh core'",true,false) + update_thread_infos("Installing certbot with snap...") + exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' snap install --classic certbot",true,false) + exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' ln -s /snap/bin/certbot /usr/bin/certbot",false,false) + exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' certbot register --email bohung@rulingcom.com --agree-tos -n",false,false) + update_thread_infos("Finish install certbot!") + certbot_path = "/usr/bin/certbot" + else + update_thread_infos("There was some error when installing snap!") + end + end + if certbot_path.present? + @site_server.has_certbot = true + @site_server.save + update_thread_infos("Setting certbot renew to cronjob...") + crontab_lines = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' crontab -l",false,false) + certbot_renew_command = crontab_lines.select{|l| l.include?("certbot") && l.include?("renew")}[0] + unless certbot_renew_command + update_thread_infos("Add certbot renew cronjob!") + certbot_renew_command = "30 2 * * 1 #{certbot_path} renew --no-self-upgrade --post-hook 'sudo service nginx restart' > /var/log/le-renew.log" + update_thread_infos(certbot_renew_command) + exec_ssh_command_by_sudo_and_see_output(ssh,"CRON=\"#{certbot_renew_command}\" && (sudo -p 'sudo password:' crontab -l; echo \"\$CRON\" ) | sudo -p 'sudo password:' crontab -",false) + end + update_thread_infos("Finish setting renew cronjob!") + end + end + end + end + @thread.update(:status=>@thread.status.merge({"status"=>"finish"})) + rescue => e + puts [e,e.backtrace] + @thread.update(:status=>{"infos"=>@thread.status["infos"].push(e.to_s),"status"=>"error"}) + end + end + end +end \ No newline at end of file