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, port: @site_server.port}) 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, port: @site_server.port}) 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 already_apt_update = false if certbot_path.blank? update_thread_infos("checking kernel version") kernel_version = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' uname -r",false,true).strip.to_f rescue 0.0 update_thread_infos("kernel_version: #{kernel_version}") if kernel_version < 4.4 update_thread_infos("Downloading certbot by using python3(since kernel < 4.4)...") exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' add-apt-repository ppa:deadsnakes/ppa -y",false) update_thread_infos("execing apt update...") exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' apt-get -y -o DPkg::options::='--force-confdef' -o DPkg::options::='--force-confold' update",true,false) already_apt_update = true update_thread_infos("Installing python3.6 python3.6-venv libaugeas0 ...") exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' apt-get install python3.6 python3.6-venv libaugeas0 -y",false) exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' rm -rf /opt/certbot/",false) update_thread_infos("generating venv for certbot ...") exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' python3.6 -m venv /opt/certbot/",false) exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' /opt/certbot/bin/pip install --trusted-host pypi.python.org --upgrade pip",false) update_thread_infos("Installing certbot on python3.6 ...") exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' /opt/certbot/bin/pip install --trusted-host pypi.python.org certbot certbot-nginx",true) exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' rm -f /usr/bin/certbot",true) exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' ln -s /opt/certbot/bin/certbot /usr/bin/certbot",true) 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 if snap_path.blank? unless already_apt_update update_thread_infos("execing apt update...") exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' apt-get -y -o DPkg::options::='--force-confdef' -o DPkg::options::='--force-confold' update",true,false) end update_thread_infos("Installing snap...") 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 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 --nginx-ctl /usr/sbin/nginx --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