{"id":18445832,"url":"https://github.com/voronenko/devops-ruby-app-demo","last_synced_at":"2025-04-15T01:16:55.263Z","repository":{"id":145345292,"uuid":"54191904","full_name":"Voronenko/devops-ruby-app-demo","owner":"Voronenko","description":"Demo repository illustrating  approaches for automated ruby application deployment","archived":false,"fork":false,"pushed_at":"2016-09-15T10:52:03.000Z","size":30,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-15T01:16:43.788Z","etag":null,"topics":["oops-to-devops"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Voronenko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2016-03-18T10:04:26.000Z","updated_at":"2018-03-30T15:56:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"d263d64f-f172-450b-aa09-929f3fe99550","html_url":"https://github.com/Voronenko/devops-ruby-app-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Voronenko%2Fdevops-ruby-app-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Voronenko%2Fdevops-ruby-app-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Voronenko%2Fdevops-ruby-app-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Voronenko%2Fdevops-ruby-app-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Voronenko","download_url":"https://codeload.github.com/Voronenko/devops-ruby-app-demo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248986316,"owners_count":21194025,"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","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":["oops-to-devops"],"created_at":"2024-11-06T07:07:35.033Z","updated_at":"2025-04-15T01:16:55.246Z","avatar_url":"https://github.com/Voronenko.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Introduction\n\nNovadays, you can get your own dedicated server up and running in a seconds. Once you get it up, do you really spent several hours to configure it for your application needs ?  Do you really want to repeat the same steps with each new server ?  In this article I will give you an idea on automated installation with Ansible, a Simple IT Automation toolkit and Ubuntu 14.04 LTS server as box OS.\n\n## Background\n\nYou would need basic understanding of ansible files syntax. if you did not play with Ansible yet, I would recommend to review some intro articles like [http://docs.ansible.com/ansible/intro.html](http://docs.ansible.com/ansible/intro.html) or perhaps one of the slideshares like [http://www.slideshare.net/robertreiz/ansible-40167296](http://www.slideshare.net/robertreiz/ansible-40167296)?\n\n## Cooking\n\nWe would need to deploy following components:   Ruby, Web server with Passenger, your application itself. For purposes of the demo, we will install well known starter Devise [https://github.com/RailsApps/rails-devise.git](https://github.com/RailsApps/rails-devise.git)\n\n### Ruby switcher chruby\n\nI used to choose RMV previously, but recently I am a fan of **chruby** - it is lightweight, quick to understand and just works - avaiable at Github [https://github.com/postmodern/chruby](https://github.com/postmodern/chruby)\n\nUpon studiing installation instructions, we automate manual installation steps with Ansible, and get a bonus: reusable recipe to install the ch_ruby.\n\n\u003cpre lang=\"C++\"\u003e---\n  - name: Ruby | Check if chruby is present\n    shell: test -x /usr/local/bin/chruby-exec\n    when: ansible_system == \"Linux\"\n    ignore_errors: yes\n    register: chruby_present\n    tags: ruby\n\n  - name: Ruby | Download chruby distribution\n    get_url: url=\"http://github.com/postmodern/chruby/archive/v{{ chruby_version }}.tar.gz\"\n             dest=\"/tmp/chruby-{{ chruby_version }}.tar.gz\"\n    when: chruby_present|failed\n    tags: ruby\n\n  - name: Ruby | unpack chruby\n    command: tar xf \"/tmp/chruby-{{ chruby_version }}.tar.gz\"\n             chdir=\"/tmp\"\n    when: chruby_present|failed\n    tags: ruby\n\n  - name: Ruby | chruby install target\n    command: make install\n             chdir=\"/tmp/chruby-{{ chruby_version }}\"\n    become: yes\n    when: chruby_present|failed\n    tags: ruby\n\n  - name: Ruby | autoload script\n    template: src=\"{{role_dir}}/templates/ch_ruby.sh.j2\" dest=/etc/profile.d/chruby.sh\n    become: yes\n    tags: ruby\u003c/pre\u003e\n\n### Ruby install\n\n**Ruby-install** is the second toolkit from the same author.  At present moment, this approach is #1 choice for me when I need to install specific Ruby version. Tool is available at Github under address [https://github.com/postmodern/ruby-install](https://github.com/postmodern/ruby-install)\n\nOnce we study ruby-install setup notes,  we can automate this steps with series of ansible steps:\n\n\u003cpre\u003e---\n  - name: Ruby | Check if ruby install is present\n    shell: test -x /usr/local/bin/ruby-install\n    when: ansible_system == \"Linux\"\n    ignore_errors: yes\n    register: rubyinstall_present\n    tags: ruby\n\n  - name: Ruby | Ruby install | package dependencies\n    apt: pkg={{ item }} state=present force=\"yes\"  update_cache=\"yes\"\n    when: ansible_system == \"Linux\"\n    with_items:\n      - build-essential\n      - libffi-dev\n      - libgdbm-dev\n      - libncurses5-dev\n      - libreadline-dev\n      - libreadline6-dev\n      - libtinfo-dev\n      - libyaml-dev\n    become: yes\n    tags: ruby\n\n  - name: Ruby | Download rubyinstall\n    get_url: url=http://github.com/postmodern/ruby-install/archive/v{{ ruby_install_version }}.tar.gz\n           dest=/tmp/ruby-install-{{ ruby_install_version }}.tar.gz\n    when: rubyinstall_present | failed\n    tags: ruby\n\n  - name: Ruby | Unpack ruby-install\n    command: tar xf /tmp/ruby-install-{{ ruby_install_version }}.tar.gz\n             chdir=/tmp\n    when: rubyinstall_present | failed\n    tags: ruby\n\n  - name: Ruby | Run ruby-install install target\n    command: make install\n           chdir=/tmp/ruby-install-{{ ruby_install_version }}\n    when: rubyinstall_present | failed\n    become: yes\n    tags: ruby\n\n  - name: Ruby | Download list of rubies available\n    command: ruby-install\n    when: rubyinstall_present | failed\n    become: yes\n    tags: ruby\n\u003c/pre\u003e\n\n### Ruby\n\nNow it is time to install Ruby.  Small comment here: if you deploy saying on shared server, you most likely would like to have an ability to have multiple ruby versions and switch between them. From other hand, if you deploy your application to the dedicated host - usually I also replace default system ruby with the same ruby version.\n\nWith tools above, ruby installation recipe is compact \u0026 clear:\n\n\u003cpre\u003e---\n  - name: Ruby | Find out if ruby_version is already installed\n    stat: path={{rubies_location}}/ruby-{{ruby_version}}\n    register: ruby_version_present\n    tags: ruby\n\n  - name: Ruby | Install ruby_version if necessary\n    command: '/usr/local/bin/ruby-install ruby {{ruby_version}}'\n    when: not ruby_version_present.stat.exists\n    become: yes\n    tags: ruby\n\n  - debug: var=\"ruby_install_setsystem\"\n\n  - name: Ruby | Update SYSTEM ruby_version if necessary\n    command: '/usr/local/bin/ruby-install --system ruby {{ruby_version}}'\n    when: option_ruby_install_setsystem\n    become: yes\n    tags: ruby\u003c/pre\u003e\n\n### Webserver \u0026 passenger\n\nThanks to Phusion Passenger team, they did a great job to provide pre-built binaries for most of the popular platforms and configurations at [https://oss-binaries.phusionpassenger.com/](https://oss-binaries.phusionpassenger.com/). This allows us to skip steps of compiling phusion passengers from source, recomplining  webserver, etc  \u0026 use pre-built binary instead.\n\nHistorically, I prefer Nginx over classic Apache, thus we will install pre-build Nginx with passenger:\n\n\u003cpre\u003e---\n  - name: Nginx | Check if is present\n    command: test -x /usr/sbin/nginx\n    when: ansible_os_family == \"Debian\"\n    ignore_errors: yes\n    register: nginx_present\n    tags: nginx\n\n  - name: Passenger | Add GPG key to apt keyring\n    apt_key: keyserver=keyserver.ubuntu.com id=561F9B9CAC40B2F7\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    tags: passenger\n    become: yes\n\n  - name: Passenger | Install needed packages\n    apt: state=present pkg=\"{{item}}\"\n    with_items:\n     - apt-transport-https\n     - ca-certificates\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    become: yes\n    tags: passenger\n\n  - name: Passenger | Add nginx extras repository\n    apt_repository: repo=\"deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main\" state=present\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    tags: passenger\n    become: yes\n\n  - name: Ruby | Install Nginx extra and Phusion Passenger\n    apt: state=present update_cache=yes pkg=\"{{item}}\"\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    with_items:\n     - nginx-extras\n     - passenger\n    become: yes\n    tags: passenger\n\n  - name: Nginx | Create sites available/enabled directories\n    file: path={{item}} state=directory mode=0755\n    with_items:\n      - /etc/nginx/sites-available\n      - /etc/nginx/sites-enabled\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    tags:\n      - nginx\n      - passenger\n    become: yes\n\n  - name: Nginx | Configure include sites-enabled\n    lineinfile: dest=/etc/nginx/nginx.conf regexp=\".*sites-enabled.*\" line=\"    include /etc/nginx/sites-enabled/*;\" insertbefore=\"}\" state=present\n    tags:\n      - nginx\n      - passenger\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    become: yes\n\n  - name: Nginx | Disable default site\n    file: path=/etc/nginx/sites-enabled/default state=absent\n    tags:\n      - nginx\n      - passenger\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    become: yes\n\n  - name: Nginx | Uncomment server_names_hash_bucket_size\n    lineinfile: dest=/etc/nginx/nginx.conf regexp=\"^(\\s*)#\\s*server_names_hash_bucket_size\" line=\"\\1server_names_hash_bucket_size 64;\" backrefs=yes\n    become: yes\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    tags:\n      - nginx\n      - passenger\n\n  - name: Nginx | Set ruby to system one\n    lineinfile: dest=/etc/nginx/nginx.conf regexp=\"^(\\s*)#\\s*passenger_ruby\" line=\"passenger_ruby /usr/local/bin/ruby;\" backrefs=yes\n    become: yes\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    tags:\n      - nginx\n      - passenger\n\n  - name: Nginx | Set ruby to system one\n    lineinfile: dest=/etc/nginx/nginx.conf regexp=\"^(\\s*)#\\s*passenger_root\" line=\"passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;\" backrefs=yes\n    become: yes\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    tags:\n      - nginx\n      - passenger\n\n  - name: Nginx | Reload\n    service: name=nginx state=reloaded\n    when: ansible_os_family == \"Debian\" and nginx_present|failed\n    tags:\n      - nginx\n      - passenger\n    become: yes\u003c/pre\u003e\n\nSeveral comments to installation script above, which might require changes in your own scenarios:\n\n1) Task named \"Create sites available/enabled directories\" \u0026 the next one - it actually implements Apache like \"sites-available / sites-enabled\" folder structure for VHosts configs. If you prefer default setup - comment this out.\n\n2) Specifiing ruby location to passenger with\n\nlineinfile: dest=/etc/nginx/nginx.conf regexp=\"^(\\s*)#\\s*passenger_ruby\" line=\"passenger_ruby /usr/local/bin/ruby;\" backrefs=yes\n\nAs you see, replacement above assumes that system ruby is used. You might want to specifiy different ruby path here.\n\nGoal of these two tasks is to take nginx.conf \u0026 set two parameters: passenger_root and passenger_ruby as per original instuctions in above comment.\n\n\u003cpre\u003e        ##\n        # Uncomment it if you installed passenger or passenger-enterprise\n        ##\n\npassenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;\npassenger_ruby /usr/local/bin/ruby;\n\n\u003c/pre\u003e\n\nHow to validate that you've installed nginx with passenger right ?\n\nExecute these commands and validate the setup:\n\n\u003cpre\u003esudo /usr/bin/passenger-config validate-install\nWhat would you like to validate?\nUse \u003cspace\u003e to select.\nIf the menu doesn't display correctly, press '!'\n\n ‣ ⬢  Passenger itself\n   ⬡  Apache\n\n-------------------------------------------------------------------------\n\n * Checking whether this Passenger install is in PATH... ✓\n * Checking whether there are no other Passenger installations... ✓\n\nEverything looks good. :-)\n\u003c/pre\u003e\n\nand /usr/sbin/passenger-memory-stats - you should see both - Nginx \u0026 passenger processes.\n\n\u003cpre\u003esudo /usr/sbin/passenger-memory-stats\nVersion: 5.0.26\nDate   : 2016-03-18 11:17:57 +0200\n------------- Apache processes -------------\n*** WARNING: The Apache executable cannot be found.\nPlease set the APXS2 environment variable to your 'apxs2' executable's filename, or set the HTTPD environment variable to your 'httpd' or 'apache2' executable's filename.\n\n--------- Nginx processes ----------\nPID   PPID  VMSize    Private  Name\n------------------------------------\n8768  9991  138.1 MB  1.1 MB   nginx: worker process\n8769  9991  137.8 MB  0.9 MB   nginx: worker process\n8770  9991  137.8 MB  0.9 MB   nginx: worker process\n8771  9991  137.8 MB  0.9 MB   nginx: worker process\n9991  1     137.8 MB  0.9 MB   nginx: master process /usr/sbin/nginx\n### Processes: 5\n### Total private dirty RSS: 4.68 MB\n\n---- Passenger processes -----\nPID   VMSize    Private  Name\n------------------------------\n8742  436.3 MB  1.0 MB   Passenger watchdog\n8745  982.9 MB  2.0 MB   Passenger core\n8756  444.5 MB  1.1 MB   Passenger ust-router\n8806  387.1 MB  69.3 MB  Passenger RubyApp: /var/www/public (production)\n### Processes: 4\n### Total private dirty RSS: 73.47 MB\nslavko@ERM:/etc/nginx$ \n\u003c/pre\u003e\n\n## Application setup itself\n\nLet's define application parameters: in particular: required OS packages to build gems, app secret - to hash the passwords, application environment parameters, database connection details.\n\n\u003cpre\u003e  app_dependencies:\n    - libsqlite3-dev\n    - libmysqlclient-dev\n    - libpq-dev\n    - git\n    - nodejs\n    - npm\n\n  app_short_name: app\n  app_env: production\n  app_domain: domain.local\n  app_secret: 82d58d3dfb91238b495a311eb8539edf5064784f1d58994679db8363ec241c745bef0b446bfe44d66cbf91a2f4e497d8f6b1ef1656e3f405b0d263a9617ac75e\n  app_repository: https://github.com/RailsApps/rails-devise.git\n#  app_repository_keyname: id_rsa_app\n  app_base_dir: /var/www\n  app_www_root: \"{{app_base_dir}}/public\"\n\n  app_env_vars:\n    - {name: SECRET_KEY_BASE, value: \"{{app_secret}}\" }\n    - {name: DATABASE_URL, value: \"postgres://{{app_db_user}}:{{app_db_password}}@{{app_db_host}}/{{app_db_name}}\"}\n    - {name: RAILS_ENV, value: \"{{app_env}}\" }\n    - {name: DOMAIN_NAME, value: \"{{app_domain}}\" } \n\n  app_db_host: localhost\n  app_db_user: app_user\n  app_db_password: app_password\n  app_db_name: app_database    \n\n  app_directories:\n    - \"{{app_base_dir}}\"\n\u003c/pre\u003e\n\nAnd application provisioning script itself, which goes into stages: OS packages dependencies, Gem dependencies (for devise it is sqlite3), checking out the source code,  patching Gem file so the ruby version matches the one installed on host + introducing production gems for uglifyjs (this is current app specifics), bundle install, patching database configuration, assets compilation, db migration, generating nginx site configuration, restarting the web server.\n\n\u003cpre\u003e---\n\n  - name: APP STUB | Dependencies\n    apt: pkg={{ item }} state=present force=\"yes\"  update_cache=\"yes\"\n    when: ansible_system == \"Linux\"\n    with_items: \"{{app_dependencies}}\"\n    become: yes\n    tags: app_stub\n\n  - name: APP STUB | Install gem dependencies\n    shell: \"gem install --no-rdoc --no-ri {{item}}\"\n    with_items:\n      - sqlite3\n    become: yes\n    tags: app_stub\n\n  - name: APP STUB | Re-create base app directory\n    file: path={{app_base_dir}} state=absent\n    become: yes\n    tags: app_stub\n\n  - name: APP STUB | Create directories\n    file: path={{item}} state=directory mode=0755 owner={{ansible_user_id}} group={{ansible_user_id}}\n    with_items: \"{{app_directories}}\"\n    become: yes\n    tags: app_stub\n\n  - name: APP STUB | Checkout app without key\n    git: repo=\"{{app_repository}}\" dest=\"{{app_base_dir}}\" accept_hostkey=\"yes\" force=\"yes\"\n    when: app_repository_keyname is not defined\n    tags: app_stub\n\n  - name: APP STUB | Install global rails gem\n    shell: gem install --no-rdoc --no-ri rails\n    become: yes\n    tags: app_stub\n\n  - name: APP STUB | Eliminate ruby req\n    lineinfile: dest=\"{{app_base_dir}}/Gemfile\" regexp=\"^(\\s*)*ruby\" line=\"ruby '{{ruby_version}}'\"\n    tags: app_stub\n\n  - name: APP STUB | gem therubyracer - uglifyjs\n    lineinfile: dest=\"{{app_base_dir}}/Gemfile\" regexp=\"^(\\s*)*gem 'therubyracer'\" line=\"gem 'therubyracer', :platforms =\u003e :ruby\" insertafter=\"^group :production do\"\n    tags: app_stub\n\n  - name: APP STUB | gem execjs - uglifyjs\n    lineinfile: dest=\"{{app_base_dir}}/Gemfile\" regexp=\"^(\\s*)*gem 'execjs'\" line=\"gem 'execjs'\" insertafter=\"^group :production do\"\n    tags: app_stub\n\n  - name: APP STUB | gem pg\n    lineinfile: dest=\"{{app_base_dir}}/Gemfile\" regexp=\"^(\\s*)*gem 'pg'\" line=\"gem 'pg'\" insertafter=\"^group :production do\"\n    tags: app_stub\n\n  - name: APP STUB | Run bundle install --path .bundle/gems --binstubs .bundle/bin\n    shell: bundle install  --path .bundle/gems --binstubs .bundle/bin\n    args:\n      chdir: \"{{app_base_dir}}\"\n    tags: app_stub\n\n  - name: APP STUB | database.yml\n    template: src=\"{{root_dir}}/templates/app/database.yml.j2\" dest=\"{{app_base_dir}}/config/database.yml\"\n    become: yes\n    tags: app_stub\n\n  - name: APP STUB | Precompile assets\n    shell: bundle exec rake assets:precompile\n    args:\n      chdir: \"{{app_base_dir}}\"\n    environment:\n      RAILS_ENV: \"{{app_env}}\"\n      DATABASE_URL: \"postgres://{{app_db_user}}:{{app_db_password}}@{{app_db_host}}/{{app_db_name}}\"\n      SECRET_KEY_BASE: \"{{app_secret}}\"\n      DOMAIN_NAME: \"{{app_domain}}\"\n    tags: app_stub\n\n  - name: APP STUB | DB Migrate\n    shell: bundle exec rake db:migrate\n    args:\n      chdir: \"{{app_base_dir}}\"\n    environment:\n      RAILS_ENV: \"{{app_env}}\"\n      DATABASE_URL: \"postgres://{{app_db_user}}:{{app_db_password}}@{{app_db_host}}/{{app_db_name}}\"\n      SECRET_KEY_BASE: \"{{app_secret}}\"\n      DOMAIN_NAME: \"{{app_domain}}\"\n    tags: app_stub\n\n  - name: APP STUB | Nginx conf\n    template: src=\"{{root_dir}}/templates/nginx_app.conf.j2\" dest=\"/etc/nginx/sites-enabled/{{app_short_name}}.conf\"\n    become: yes\n    tags: app_stub\n\n  - name: Nginx | Reload\n    service: name=nginx state=reloaded\n    become: yes\n    tags: app_stub\n\u003c/pre\u003e\n\nIn particular, we patch database config/database.yml with real connection details\n\n\u003cpre\u003e# On Heroku and other platform providers, you may have a full connection URL\n# available as an environment variable. For example:\n#\n#   DATABASE_URL=\"postgres://myuser:mypass@localhost/somedatabase\"\n#\n# You can use this database configuration with:\n#\n   production:\n     url: \u003c%= ENV['DATABASE_URL'] %\u003e\u003c/pre\u003e\n\nand we patch Nginx app site config to provide app environment variables to ruby app with passenger_env_var instructions.\n\n\u003cpre\u003eserver {\n  listen 80 default_server;\n  passenger_enabled on;\n\n  {% for envvar in app_env_vars %}\n  passenger_env_var {{ envvar.name }} \"{{ envvar.value }}\";\n  {% endfor %}\n\n  passenger_app_env {{app_env}};\n  root {{app_www_root}};\n}\n\u003c/pre\u003e\n\n## Running the code\n\nLet's execute provisioning \u0026 test it, for purposes of the demo - we will use local postgres as a DB\n\n\u003cpre\u003e---\n- hosts: www\n\n  vars:\n    - root_dir: ..\n\n  roles:\n     - {\n         role: \"sa-postgres\",\n         option_create_app_user: true\n       }\n     - {\n         role: \"sa-ruby\",\n         ruby_install_setsystem: true,\n         ruby_version: 2.3.0,\n\n         option_install_sampleapp: true,\n         option_install_nginx_passenger: true\n       }\n\n\u003c/pre\u003e\n\nOnce application provisioning process is over:\n\n\u003cpre\u003eTASK: [sa-ruby | Nginx | Reload] ********************************************** \nchanged: [192.168.0.17] =\u003e {\"changed\": true, \"name\": \"nginx\", \"state\": \"started\"}\n\nPLAY RECAP ******************************************************************** \n192.168.0.17               : ok=55   changed=46   unreachable=0    failed=0   \n\nPlay run took 23 minutes\n\u003c/pre\u003e\n\nSo, depending on network speed, you have your application installed.\n\nLet's check by ip address: \n\n![Deployed application](https://raw.githubusercontent.com/Voronenko/devops-ruby-app-demo/master/docs/app_deployed.png)\n\n## Points of Interest\n\nNow you aware of another way to deploy your ruby applications.\n\nDemo deployment script is available at [https://github.com/Voronenko/devops-ruby-app-demo](https://github.com/Voronenko/devops-ruby-app-demo) , recipes packed as ansible reusable role available at [https://github.com/softasap/sa-ruby](https://github.com/softasap/sa-ruby)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvoronenko%2Fdevops-ruby-app-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvoronenko%2Fdevops-ruby-app-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvoronenko%2Fdevops-ruby-app-demo/lists"}