PageRenderTime 108ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/vlad/uberspace.rb

https://github.com/dennisreimann/vlad-extras
Ruby | 258 lines | 163 code | 21 blank | 74 comment | 2 complexity | f960f948bd1ba765f4c12cd2691a4f04 MD5 | raw file
  1. # encoding: utf-8
  2. #
  3. # This recipe provides setup and maintenance tasks for Rails apps hosted on
  4. # [Uberspace](http://uberspace.de). Most of this recipe has been inspired by
  5. # [uberspacify](https://github.com/yeah/uberspacify), a gem which provides
  6. # this functionality for Capistrano.
  7. #
  8. # Tasks:
  9. #
  10. # - vlad:uberspace:setup # all-in-one setup task
  11. # - vlad:uberspace:setup_svscan
  12. # - vlad:uberspace:setup_service
  13. # - vlad:uberspace:setup_domain_symlink
  14. # - vlad:uberspace:create_database_yml
  15. # - vlad:uberspace:create_reverse_proxy_htaccess
  16. # - vlad:uberspace:reload_service
  17. # - vlad:uberspace:remove_service
  18. # - vlad:start_app
  19. # - vlad:restart_app
  20. # - vlad:stop_app
  21. #
  22. # Hint: uberspace doesn't allow concurrent ssh connections.
  23. # You will need to use shared ssh connections, otherwise vlad remote tasks won't work as expected.
  24. # Add the followiwng lines at the top of your ~/.ssh/config to enable ssh shared connections:
  25. # ControlMaster auto
  26. # ControlPath /tmp/ssh_mux_%h_%p_%r
  27. # ControlPersist 15m
  28. #
  29. # Example Configuration:
  30. #
  31. # set :app_server_port, 87654
  32. # set :app_server_start_cmd, "#{bundle_cmd} exec thin start -p #{app_server_port} -e #{rails_env}"
  33. #
  34. # Notes:
  35. #
  36. # The deploy_to gets set for you, because the rails code needs to live somewhere
  37. # under /var/www/virtual/ so that Apache can access it. It's got a sane default
  38. # which you can override as long as you keep the above in mind.
  39. # The uberspace_home and uberspace_service variables don't need to be touched.
  40. #
  41. # Your setup tasks may look like this, if you bring your own database.yml (usually
  42. # with vlad:copy:shared) you can remove the vlad:uberspace:create_database_yml task:
  43. #
  44. # set :setup_tasks, %w(
  45. # vlad:setup_app
  46. # vlad:copy:shared
  47. # vlad:assets:create_shared_dir
  48. # vlad:uberspace:setup
  49. # vlad:uberspace:create_database_yml
  50. # )
  51. #
  52. # Unless you ship your own public/.htaccess file (which may include custom config)
  53. # you should include the vlad:uberspace:create_reverse_proxy_htaccess after the
  54. # vlad:update task, so that everything works as expected:
  55. #
  56. # set :deploy_tasks, %w(
  57. # vlad:update
  58. # vlad:uberspace:create_reverse_proxy_htaccess
  59. # [...]
  60. # )
  61. set(:deploy_to) { "/var/www/virtual/#{user}/rails/#{application}" }
  62. set(:uberspace_home) { "/home/#{user}" }
  63. set(:uberspace_service) { "#{uberspace_home}/service/rails-#{application}" }
  64. namespace :vlad do
  65. namespace :uberspace do
  66. desc 'Setup your Uberspace for deploying a Rails app'
  67. remote_task :setup do
  68. %w(svscan service domain_symlink).each do |task|
  69. Rake::Task["vlad:uberspace:setup_#{task}"].invoke
  70. end
  71. end
  72. desc 'Setup custom services for your user'
  73. remote_task :setup_svscan do
  74. puts '[Uberspace] Setup svscan'
  75. run 'uberspace-setup-svscan ; echo' # echo to ensure non-error exit
  76. end
  77. desc 'Setup service script for the app'
  78. remote_task :setup_service do
  79. puts '[Uberspace] Setup service'
  80. unless app_server_start_cmd
  81. raise(Rake::ConfigurationError,
  82. 'Please specify the application server start command via the :app_server_start_cmd variable')
  83. end
  84. etc_dir = "#{uberspace_home}/etc/run-rails-#{application}"
  85. # install
  86. run "mkdir -p #{etc_dir}"
  87. run "mkdir -p #{etc_dir}/log"
  88. put "#{etc_dir}/run" do
  89. <<-EOF
  90. #!/bin/bash
  91. export HOME=#{uberspace_home}
  92. source $HOME/.bash_profile
  93. cd #{current_path}
  94. exec #{app_server_start_cmd} 2>&1
  95. EOF
  96. end
  97. put "#{etc_dir}/log/run" do
  98. <<-EOF
  99. #!/bin/sh
  100. exec multilog t ./main
  101. EOF
  102. end
  103. run "chmod +x #{etc_dir}/run"
  104. run "chmod +x #{etc_dir}/log/run"
  105. run "ln -nfs #{etc_dir} #{uberspace_service}"
  106. end
  107. desc 'Symlink domain to current path'
  108. remote_task :setup_domain_symlink do
  109. puts '[Uberspace] Setup domain symlink'
  110. # ensure that there is a current public path we can symlink to
  111. Rake::Task['vlad:update'].invoke unless VladExtras::Remote.exists?(current_path)
  112. public_path = "#{current_path}/public"
  113. domain_path = "/var/www/virtual/#{user}/#{domain}"
  114. run "mkdir -p #{public_path}" unless VladExtras::Remote.exists?(public_path)
  115. run "ln -nfs #{public_path} #{domain_path}"
  116. end
  117. desc 'Creates shared/config/database.yml from your my.cnf'
  118. remote_task :create_database_yml do
  119. puts '[Uberspace] Create database.yml'
  120. database_yml = "#{shared_path}/config/database.yml"
  121. db_conf = run "cat #{uberspace_home}/.my.cnf"
  122. db_port = db_conf.match(/^port=(\w+)/)[1]
  123. db_username = db_conf.match(/^user=(\w+)/)[1]
  124. db_password = db_conf.match(/^password=(\w+)/)[1]
  125. db_socket = db_conf.match(/^socket=(.*)$/)[1]
  126. content = <<-EOF
  127. #{rails_env}:
  128. adapter: mysql2
  129. encoding: utf8
  130. reconnect: false
  131. pool: 5
  132. host: localhost
  133. port: #{db_port}
  134. database: #{user}_#{application}
  135. username: #{db_username}
  136. password: #{db_password}
  137. socket: #{db_socket}
  138. EOF
  139. # check for already existing htaccess
  140. if VladExtras::Remote.exists?(database_yml)
  141. puts "\nYou already have a custom database.yml, located at\n#{database_yml}"
  142. puts "Please verify that it contains the following lines in order to work properly:"
  143. puts "\n#{content}\n"
  144. else
  145. # otherwise install it
  146. unless app_server_port
  147. raise(Rake::ConfigurationError,
  148. 'Please specify the application server port via the :app_server_port variable')
  149. end
  150. run "mkdir -p #{File.dirname(database_yml)}"
  151. put database_yml do
  152. content
  153. end
  154. run "chmod +r #{database_yml}"
  155. end
  156. end
  157. desc 'Creates .htaccess with Apache reverse proxy config'
  158. remote_task :create_reverse_proxy_htaccess do
  159. puts '[Uberspace] Setup Apache reverse proxy'
  160. htaccess = "#{current_path}/public/.htaccess"
  161. content = <<-EOF
  162. RewriteEngine On
  163. RewriteBase /
  164. # ensure the browser supports gzip encoding
  165. RewriteCond %{HTTP:Accept-Encoding} \\b(x-)?gzip\\b
  166. RewriteCond %{REQUEST_FILENAME}.gz -s
  167. RewriteRule ^(.+) $1.gz [L]
  168. # ensure correct Content-Type and add encoding header
  169. <FilesMatch \\.css\\.gz$>
  170. ForceType text/css
  171. Header set Content-Encoding gzip
  172. </FilesMatch>
  173. <FilesMatch \\.js\\.gz$>
  174. ForceType text/javascript
  175. Header set Content-Encoding gzip
  176. </FilesMatch>
  177. # cache assets like forever
  178. <FilesMatch \\.(js|css|gz|jpe?g|gif|png|ico)$>
  179. Header unset ETag
  180. FileETag None
  181. ExpiresActive On
  182. ExpiresDefault "access plus 1 year"
  183. </FilesMatch>
  184. # maintenance mode
  185. ErrorDocument 503 /system/maintenance.html
  186. RewriteCond %{REQUEST_URI} !.(css|gif|jpg|png)$
  187. RewriteCond #{current_path}/public/system/maintenance.html -f
  188. RewriteCond %{SCRIPT_FILENAME} !maintenance.html
  189. RewriteRule ^.*$ - [redirect=503,last]
  190. # let rails handle everything else
  191. RewriteCond %{REQUEST_FILENAME} !-f
  192. RewriteRule ^(.*)$ http://localhost:#{app_server_port}/$1 [P]
  193. EOF
  194. # check for already existing htaccess
  195. if VladExtras::Remote.exists?(htaccess)
  196. puts "\nYou already have a custom .htaccess, located at\n#{htaccess}"
  197. puts "Please verify that it contains the following lines in order to work properly:"
  198. puts "\n#{content}\n"
  199. else
  200. # otherwise install it
  201. unless app_server_port
  202. raise(Rake::ConfigurationError,
  203. 'Please specify the application server port via the :app_server_port variable')
  204. end
  205. put htaccess do
  206. content
  207. end
  208. run "chmod +r #{htaccess}"
  209. end
  210. end
  211. desc 'Reloads service script'
  212. remote_task :reload_service do
  213. puts '[Uberspace] Reload service'
  214. run "svc -h #{uberspace_service}"
  215. end
  216. desc 'Removes service script'
  217. remote_task :remove_service do
  218. puts '[Uberspace] Remove service'
  219. run "cd #{uberspace_service}"
  220. run "rm #{uberspace_service}"
  221. run "svc -dx . log"
  222. run "rm -rf #{uberspace_home}/etc/run-rails-#{application}"
  223. end
  224. end
  225. desc 'Starts the application server'
  226. remote_task :start_app, :roles => :app do
  227. run "svc -u #{uberspace_service}"
  228. end
  229. desc 'Stops the application server'
  230. remote_task :stop_app, :roles => :app do
  231. run "svc -d #{uberspace_service}"
  232. end
  233. desc 'Restarts the application server'
  234. remote_task :restart_app, :roles => :app do
  235. run "svc -du #{uberspace_service}"
  236. end
  237. end