├── 12_Beyond.md ├── 07_Intro_To_Chef.md ├── 05_Setting_Up_Monitoring.md ├── 10_Intro_To_Chef_Server.md ├── 06_Too_Big_For_One_Instance.md ├── 08_Crafting_A_Server_With_Chef_Solo.md ├── 11_TDDing_Your_Infrastructure_With_Chef.md ├── 09_Spinning_Up_Multiple_Servers_With_Chef_Solo.md ├── README.md ├── 01_Intro.md ├── 02_Intro_To_A_Web_Server.md ├── 04_Deploying_With_Capistrano.md ├── LICENSE └── 03_Hand_Crafting_A_Web_Server.md /12_Beyond.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /07_Intro_To_Chef.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /05_Setting_Up_Monitoring.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /10_Intro_To_Chef_Server.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /06_Too_Big_For_One_Instance.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /08_Crafting_A_Server_With_Chef_Solo.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /11_TDDing_Your_Infrastructure_With_Chef.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /09_Spinning_Up_Multiple_Servers_With_Chef_Solo.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Operations for Developers 2 | ================== 3 | 4 | At the 2014 Chef Community Summit, I helped lead a session on training developers without a sysadmin background Chef. 5 | 6 | I came from a development background myself and found Chef when I became responsible for my own QA, Staging, and Production systems. The learning curve was very high, especially because so many of Chef's resources are geared toward Sysadmins new to development rather than developers new to system administration. 7 | 8 | This experimental curriculum attempts to help fill this need. It is very much a work in progress, if you'd like to contribute feel free to fork the repo and submit a pull request, I welcome contributions and input! 9 | 10 | Copyright 2015 Nellie Shamrell-Harrington 11 | 12 | Licensed under the Apache License, Version 2.0 (the "License"); 13 | you may not use this file except in compliance with the License. 14 | You may obtain a copy of the License at 15 | 16 | http://www.apache.org/licenses/LICENSE-2.0 17 | 18 | Unless required by applicable law or agreed to in writing, software 19 | distributed under the License is distributed on an "AS IS" BASIS, 20 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | See the License for the specific language governing permissions and 22 | limitations under the License. 23 | -------------------------------------------------------------------------------- /01_Intro.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ## Pre-requisites 4 | 5 | This tutorial assumes a basic familiarity with Ruby on Rails, the UNIX or OS X command line, and that you have at least deployed an application to a service such as Heroku. 6 | 7 | ## Sample Rails Application 8 | 9 | Please download this [sample Rails application](https://github.com/nellshamrell/widgetworld) - this is the application we will configure and deploy. 10 | 11 | You will also need an Ubuntu 14.04 Virtual Machine, see the next section for information on how to get one. 12 | 13 | ## Getting a VM 14 | 15 | ### Getting a Local VM 16 | 17 | My favorite way to run a local VM is using [Vagrant](https://www.vagrantup.com/) and [Virtual Box](https://www.virtualbox.org/) 18 | 19 | Follow the Vagrant setup and installation instructions located [here](https://docs.vagrantup.com/v2/getting-started/index.html) 20 | 21 | After you have familiarized yourself with Vagrant following those instructions, create a new directory for this tutorial 22 | ```bash 23 | mkdir ops_for_developers 24 | ``` 25 | 26 | The navigate into that directory. 27 | 28 | ```bash 29 | cd ops_for_developers 30 | ``` 31 | 32 | Once there, create a new Vagrant file - this time for an Ubuntu 14.04 server 33 | 34 | ```bash 35 | vagrant init ubuntu/trusty64 36 | ``` 37 | 38 | Then start your new virtual server. The first time you run this command it will take a little bit and you will see lots of output. 39 | ```bash 40 | vagrant up 41 | ``` 42 | 43 | Once this is complete, ssh into your new virtual server with 44 | ```bash 45 | vagrant ssh 46 | ``` 47 | 48 | ### Getting a Cloud VM 49 | 50 | TODO - Add instructions for obtaining and AWS VM, Azure VM, etc. 51 | -------------------------------------------------------------------------------- /02_Intro_To_A_Web_Server.md: -------------------------------------------------------------------------------- 1 | If you haven't already, ssh to your VM as root. 2 | 3 | ## Ubuntu 4 | 5 | Ubuntu is a commonly used both as a desktop and as a server platform. For a thorough introduction to Ubuntu Server, I recommend the [Ubuntu Server Book](http://www.amazon.com/Official-Ubuntu-Server-Book-Edition/dp/0133017532#). Now that you're ssh'd into the VM, let's take a look at what has been installed with Ubuntu 14.04. 6 | 7 | ```bash 8 | (VM) $ ls / 9 | ``` 10 | 11 | This will show you a list of directories that were created when you installed Ubuntu. Let's take a look at the directories we will use in this curriculum. 12 | 13 | ### etc 14 | Both your server and *services* that run on your server require config files. You can alter these files to change how your servers or services run. This directory is where those config files live. (Source: [Ubuntu Server Book](http://www.amazon.com/Official-Ubuntu-Server-Book-Edition/dp/0133017532#)) 15 | 16 | ### var 17 | This directory stores files and directories who's sizes vary (hence the "var" name of the directory). This includes all system logs and web server documents. Of particular note: 18 | * /var/log stores all system logs. If a service is returning errors, this is a good place to look for the log that will help you troubleshoot. 19 | * /var/www stores all web documents if your server is a web server. Our Rails app will live in this directory when we deploy it. 20 | (Source: [Ubuntu Server Book](http://www.amazon.com/Official-Ubuntu-Server-Book-Edition/dp/0133017532#)) 21 | 22 | ## Parts of a Rails Web Server 23 | 24 | There are many types of servers that can be run with Ubuntu (DNS servers, web servers, mail servers, etc.). 25 | 26 | In this tutorial we will be configuring an Ubuntu *web server*. There are three main parts that make up a server which can run a Rails application. We will configure each of these parts shortly. For now, here is a brief intro to each piece: 27 | 28 | ### Web Server 29 | We will be using [Apache](http://httpd.apache.org/) as the software to run our web server. 30 | 31 | For an excellent explanation of what a web server is and an intro to Apache, please see [this outstanding article](http://code.tutsplus.com/tutorials/an-introduction-to-apache--net-25786) 32 | 33 | ### Application Server 34 | Apache cannot serve up Rails applications by default. We need to add an additional service called an application server in order to make it work. 35 | 36 | In this tutorial, we will be using [Phusion Passenger](https://www.phusionpassenger.com/). 37 | 38 | Confused about the difference between a web server like Apache and an application server like Passenger? You are not alone. Check out this fantastic [explanation on Stack Overflow](http://stackoverflow.com/a/4113570). 39 | 40 | ### Database 41 | Rails applications need a database. By default, Rails uses SQLite, but in this tutorial we're going to use [PostgreSQL](http://www.postgresql.org/). 42 | 43 | SQLite, PostgreSQL, and MySQL are all common databases used with Rails. For a detailed explanation of the differences among these databases, please see [this article](https://www.digitalocean.com/community/tutorials/sqlite-vs-mysql-vs-postgresql-a-comparison-of-relational-database-management-systems) 44 | 45 | Let's move onto the next article and start actually configuring these pieces! 46 | 47 | -------------------------------------------------------------------------------- /04_Deploying_With_Capistrano.md: -------------------------------------------------------------------------------- 1 | ## 1. Set Up Capistrano 2 | 3 | Capistrano lives on the local machine you deploy from rather than on the VM itself. We will be using Capistrano 3 (NOTE: this version of Capistrano is very different from previous versions, be sure you are using version 3!) 4 | 5 | If you haven't already, please clone this [sample Rails application](https://github.com/nellshamrell/widgetworld) onto your LOCAL machine, this is the application we will use Capistrano to deploy to our VM. 6 | 7 | ```bash 8 | (Local) $ git clone git@github.com:nellshamrell/widgetworld.git 9 | ``` 10 | 11 | Change into the directory where you cloned this application. 12 | 13 | i.e. if you cloned the Rails app into a directory called "widgetworld" 14 | 15 | ```bash 16 | (Local) $ cd widgetworld 17 | ``` 18 | Next, let's install Capistrano and some helpful other gems. 19 | 20 | In your Gemfile, add these lines 21 | 22 | ```bash 23 | group :development do 24 | gem 'capistrano', '~> 3.1' 25 | gem 'capistrano-rails', '~> 1.1' 26 | gem 'capistrano-rvm' 27 | end 28 | ``` 29 | 30 | Then run 31 | ```bash 32 | (Local) $ bundle 33 | ``` 34 | 35 | There is also some special additional installation for capistrano. Run this command, which will add some additional Capistrano config files. 36 | ```bash 37 | (Local) $ cap install 38 | ``` 39 | 40 | Next, open your Capfile in your favorite editor 41 | 42 | ```bash 43 | (Local) $ vi Capfile 44 | ``` 45 | 46 | Uncomment this line 47 | 48 | ```bash 49 | # require 'capistrano/rvm' 50 | ``` 51 | 52 | So it looks like this 53 | 54 | ```bash 55 | require 'capistrano/rvm' 56 | ``` 57 | 58 | Later on we'll be storing our database credentials (including password) in config/database.yml. To avoid accidentally committing this to our potentially public repo, let's first make a copy of the file to serve as an example 59 | 60 | ```bash 61 | (Local) $ cp config/database.yml config/database_example.yml 62 | ``` 63 | 64 | The open up your .gitignore file with your favorite editor 65 | 66 | ```bash 67 | (Local) $ vi .gitignore 68 | ``` 69 | 70 | And add this line to the file 71 | 72 | ```bash 73 | config/database.yml 74 | ``` 75 | 76 | This will keep the database.yml file out of any git commits, histories, or repos. 77 | 78 | While we're at it, let's also add config/secrets.yml. Widget World is a Rails 4 application and Rails 4 added the secrets configuration file to contain credentials. This is not something we want possible exposed to the world in source control, so add this line to your .gitignore file, then save and close the file. 79 | 80 | ```bash 81 | config/secrets.yml 82 | ``` 83 | 84 | Next, open up the config/deploy.rb file with your favorite text editor 85 | 86 | ```bash 87 | (Local) $ vi config/deploy.rb 88 | ``` 89 | 90 | Change these to lines 91 | ```bash 92 | set :application, 'my_app_name' 93 | set :repo_url, 'git@example.com:me/my_repo.git' 94 | ``` 95 | 96 | To this 97 | 98 | ```bash 99 | set :application, 'widgetworld' 100 | set :repo_url, 'git@github.com:nellshamrell/widgetworld.git' 101 | ``` 102 | 103 | Then change this line 104 | ```bash 105 | # set :deploy_to, '/var/www/my_app_name' 106 | ``` 107 | 108 | To this 109 | 110 | ```bash 111 | set :deploy_to, '/var/www/widgetworld' 112 | ``` 113 | 114 | Then uncomment this line 115 | 116 | ```bash 117 | set :scm, :git 118 | ``` 119 | 120 | And uncomment this line 121 | 122 | ```bash 123 | set :linked_files, fetch(:linked_files, []).push('config/database.yml') 124 | ``` 125 | 126 | Finally, uncomment this line 127 | ```bash 128 | set :linked_dirs, fetch(:linked_dirs, []).push('bin', 'log', 'tmp/pids', 'tm p/cache', 'tmp/sockets', 'vendor/bundle', 'public/system') 129 | ``` 130 | 131 | And add this sequence of lines right after "namespace :deploy do" 132 | ```bash 133 | namespace :deploy do 134 | 135 | 136 | desc 'Restart application' 137 | task :restart do 138 | on roles(:app), in: :sequence, wait: 5 do 139 | # This restarts Passenger 140 | execute :mkdir, '-p', "#{ release_path }/tmp" 141 | execute :touch, release_path.join('tmp/restart.txt') 142 | end 143 | end 144 | 145 | after :publishing, :restart 146 | ``` 147 | 148 | In the changes to config/deploy.rb we specified that we would be deploying our application to a directory in /var/www on the VM. Since the deploy user will be doing the actual deploy, let's change the owner of this directory to deploy 149 | 150 | ```bash 151 | (VM) $ sudo chown deploy:deploy /var/www 152 | ``` 153 | 154 | Finally, we need to make some changes to config/deploy/production.rb (back on your local machine) 155 | 156 | Change these lines 157 | 158 | ```bash 159 | role :app, %w{deploy@example.com} 160 | role :web, %w{deploy@example.com} 161 | role :db, %w{deploy@example.com} 162 | ``` 163 | 164 | To this 165 | 166 | ```bash 167 | role :app, %w{deploy@192.168.33.10} 168 | role :web, %w{deploy@192.168.33.10} 169 | role :db, %w{deploy@192.168.33.10} 170 | ``` 171 | 172 | And change this line 173 | 174 | ```bash 175 | server 'example.com', user: 'deploy', roles: %w{web app}, my_property: :my_value 176 | ``` 177 | 178 | To this: 179 | 180 | ```bash 181 | server '192.168.33.10', user: 'deploy', roles: %w{web app}, my_property: :my_value 182 | ``` 183 | 184 | Remember how we added config/database.yml to .gitignore above so it wouldn't be committed or deployed? Now we need to create this file on the VM itself. 185 | 186 | 187 | To check whether the application is ready to be deployed with capistrano, run 188 | 189 | ```bash 190 | (Local) $ cap production deploy:check 191 | ``` 192 | 193 | It will likely error out the first time, telling you that /var/www/widgetworld/shared/config/database.yml does not exist on the VM. To fix this: 194 | 195 | Create and open this file on your VM. 196 | ```bash 197 | (VM) $ vim /var/www/widgetworld/shared/config/database.yml 198 | ``` 199 | 200 | Then copy the contents from config/database.yml in the widgetworld directory on your local machine, then paste them into this file on your VM. 201 | 202 | You'll need to make some changes under the 'production' section of database.yml on your VM. 203 | 204 | Change the username to "deploy" and the password to whatever password you set for the deploy postgres user when you created it. 205 | 206 | It should look like this: 207 | 208 | ```bash 209 | production: 210 | <<: *default 211 | database: widgetworld_production 212 | username: deploy 213 | password: #{password you set for the deploy user of postgres} 214 | ``` 215 | 216 | Save and close the file. 217 | 218 | Run the check again. 219 | ```bash 220 | (Local) $ cap production deploy:check 221 | ``` 222 | 223 | If it does not return an error and exits with a line similar to: 224 | 225 | ```bash 226 | DEBUG [7f34dcb9] Finished in 0.004 seconds with exit status 0 (successful). 227 | ``` 228 | 229 | Then we're ready to deploy! 230 | 231 | ## 2. Deploying with Capistrano 232 | 233 | Deploy with 234 | 235 | ```bash 236 | (Local) $ cap production deploy 237 | ``` 238 | 239 | Now, navigate to the site's folder on your VM. 240 | 241 | ```bash 242 | (VM) $ cd /var/www/widgetworld/current 243 | ``` 244 | 245 | And run bundler in this directory. 246 | 247 | ```bash 248 | (VM) $ bundle 249 | ``` 250 | 251 | Next, we need to add in an environmental variable to be used by our secrets configuration file. First, copy the contents of the config/secrets.yml file in your local Widget World repository. Then create this file in the /var/www/widgetworld/current directory on your VM. 252 | 253 | ```bash 254 | (VM) $ vim /var/www/widgetworld/current/database.yml 255 | ``` 256 | 257 | And paste the contents copied from your local repo. 258 | 259 | Notice that the file references an environmental variable for the production environment 260 | 261 | ```bash 262 | # Do not keep production secrets in the repository, 263 | # instead read values from the environment. 264 | production: 265 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 266 | ``` 267 | 268 | Save and quit config/secrets.yml 269 | 270 | We need to create this environmental variable. To do this, we first need to generate a secret key. 271 | 272 | Back on the command line in your VM, run this command: 273 | 274 | ```bash 275 | (VM) $ RAILS_ENV=production rake secret 276 | ``` 277 | 278 | This will return a long string to be used as your secret key base. Copy it. 279 | 280 | If you receive a "Could not find a JavaScript runtime" error, run 281 | ```bash 282 | (VM) $ sudo apt-get install nodejs 283 | ``` 284 | 285 | Now let's create the environmental variable to store this key. Open up your bash profile in an editor: 286 | 287 | ```bash 288 | (VM) $ vi ~/.bash_profile 289 | ``` 290 | 291 | And add this line to the end of the file, replacing `GENERATED_CODE` with your secret key base. 292 | 293 | ```bash 294 | (VM) $ export SECRET_KEY_BASE=GENERATED_CODE 295 | ``` 296 | 297 | Save and close the file, then reload your bash profile 298 | 299 | ```bash 300 | (VM) $ source ~/.bash_profile 301 | ``` 302 | 303 | You can then make sure this variable is set correctly by running 304 | ```bash 305 | (VM) $ echo $SECRET_KEY_BASE 306 | ``` 307 | 308 | Next, create the database for your Rails application and run migrations with these commands 309 | ```bash 310 | (VM) $ RAILS_ENV=production rake db:create 311 | (VM) $ RAILS_ENV=production rake db:migrate 312 | ``` 313 | 314 | (NOTE: This section of the tutorial was inspired by this [Stack Overflow Response](http://stackoverflow.com/a/26172408) 315 | 316 | 317 | Finally, we need to make Apache aware of our new site. Add this to 318 | /etc/apache2/apache2.conf in your VM 319 | 320 | ```bash 321 | 322 | ServerName 192.168.33.10 323 | DocumentRoot /var/www/widgetworld/current/public 324 | 325 | # This relaxes Apache security settings. 326 | AllowOverride all 327 | # MultiViews must be turned off. 328 | Options -MultiViews 329 | 330 | 331 | ``` 332 | 333 | And restart Apache 334 | ```bash 335 | (VM) $ sudo service apache2 restart 336 | ``` 337 | 338 | Navigate back to your site in your browser. 339 | 340 | If you receive a passenger error "Could not find a JavaScript runtime", run 341 | ```bash 342 | (VM) $ sudo apt-get install nodejs 343 | ``` 344 | 345 | The restart Apache again 346 | ```bash 347 | (VM) $ sudo service apache2 restart 348 | ``` 349 | 350 | And congratulations! You now have a working web server that you have deployed your application to and it works! 351 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2015 Nellie Shamrell-Harrington 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /03_Hand_Crafting_A_Web_Server.md: -------------------------------------------------------------------------------- 1 | For this lesson, you should be ssh'd into your Virtual Machine (Virtual Machine) you created in the previous lesson. 2 | 3 | We will now be running commands both on your VM and local machine. 4 | 5 | If you need to run a command on your VM, it will be denoted like this: 6 | 7 | ```bash 8 | (VM) $ cd this_directory 9 | ``` 10 | 11 | If you need to run a command on your local machine, it will be denoted like this 12 | 13 | ```bash 14 | (Local) $ cd this_directory 15 | ``` 16 | ## 1. Create a deploy user 17 | 18 | You will be prompted to set a password for this user. Record this for reference later. 19 | 20 | ```bash 21 | (VM) $ sudo adduser deploy 22 | ``` 23 | 24 | Add this user to the sudo users group. This will allow the user to use sudo to run commands. 25 | 26 | ```bash 27 | (VM) $ sudo adduser deploy sudo 28 | ``` 29 | 30 | Next, let's allow the deploy user to use sudo without be prompted for a password. A great way to do this with recent versions of sudo is to create a sudo config file for the deploy user. 31 | 32 | Create the file with your text editor of choice (here I use vi) 33 | 34 | ```bash 35 | (VM) $ sudo vi /etc/sudoers.d/deploy 36 | ``` 37 | 38 | Add this line to the file. 39 | 40 | ```bash 41 | deploy ALL=(ALL) NOPASSWD:ALL 42 | ``` 43 | Then save and quit the file. 44 | 45 | And, finally, restart the sudo service so the changes go into affect (yes, we're using sudo to restart the sudo service) 46 | 47 | ```bash 48 | (VM) $ sudo service sudo restart 49 | ``` 50 | 51 | Switch to the deploy user account (you will be prompted for the password you entered for the deploy user above). 52 | 53 | ```bash 54 | (VM) $ su deploy 55 | ``` 56 | ## 2. Install SSH 57 | 58 | We will need to be ssh into the server as the deploy user. In order to do this, we need to install OpenSSH Server on the VM. 59 | 60 | ```bash 61 | (VM) $ sudo apt-get install openssh-server 62 | ``` 63 | 64 | On your local machine, find your public ssh key by running 65 | 66 | ```bash 67 | (Local) $ cat ~/.ssh/your_public_key.pub 68 | ``` 69 | 70 | Copy this to your clipboard. 71 | 72 | Back in your VM, create an ssh directory 73 | 74 | ```bash 75 | (VM) $ mkdir ~/.ssh 76 | ``` 77 | 78 | Create an authorized_keys file in the ssh directory using whichever editor you prefer (I'm a vi/vim user myself) 79 | 80 | ```bash 81 | (VM) $ sudo vi ~/.ssh/authorized_keys 82 | ``` 83 | 84 | Paste the ssh key from your local machine into this file. Save and quit the file. 85 | 86 | Now it's time to try ssh'ing out the VM as the deploy user. Follow the appropriate steps below. 87 | 88 | ### SSHing with Vagrant 89 | 90 | Leave your vagrant machine running, but open a new terminal shell on your local machine. 91 | 92 | SSH into your VM from the new shell as the deploy user following the appropriate guidelines below. 93 | 94 | Vagrant VMs are a little complicated to ssh into outside of the normal vagrant commands. In the same directory as your Vagrant file (but NOT within the Vagrant machine itself) run: 95 | 96 | ```bash 97 | (local) $ vagrant ssh-config > vagrant-ssh 98 | ``` 99 | 100 | Open vagrant ssh with your favorite text editor. My favorite is vi/vim. 101 | 102 | ```bash 103 | (local) $ vim vagrant-ssh 104 | ``` 105 | 106 | Change this 107 | 108 | ```bash 109 | User vagrant 110 | ``` 111 | 112 | To this 113 | 114 | ```bash 115 | User deploy 116 | ``` 117 | 118 | Then change this line 119 | ```bash 120 | IdentityFile /Users/path/to/vagrant/key 121 | ``` 122 | 123 | To this - remember, include only the path to the file containing your private key, NOT the contents of the key itself! 124 | ```bash 125 | IdentityFile path/to/local/private/rsa/key 126 | ``` 127 | 128 | Save and quit the file. 129 | 130 | Next, ssh into your VM 131 | ```bash 132 | (local) $ ssh -F vagrant-ssh default 133 | ``` 134 | 135 | ### With AWS 136 | 137 | ### With Azure 138 | 139 | ### Securing SSH 140 | 141 | Now that SSH is installed, there are few needed steps to add security to the VM. 142 | 143 | First, on your VM, edit the sshd_config with your editor of choice (here I use vi) 144 | 145 | ```bash 146 | (VM) $ sudo vi /etc/ssh/sshd_config 147 | ``` 148 | 149 | First, to disable root login via ssh change this line 150 | ```bash 151 | PermitRootLogin without-password 152 | ``` 153 | to this 154 | ```bash 155 | PermitRootLogin no 156 | ``` 157 | 158 | Then, to disable password authentication, change this line 159 | ```bash 160 | PasswordAuthentication yes 161 | ``` 162 | 163 | to this 164 | ```bash 165 | PasswordAuthentication no 166 | ``` 167 | 168 | Save and quit the file, then restart the ssh service to load the changes 169 | 170 | ```bash 171 | (VM) $ sudo /etc/init.d/ssh restart 172 | ``` 173 | 174 | ## 3. Install Ruby 175 | 176 | In order to install Ruby on our VM, we first need to add some packages to the systems. 177 | 178 | ### Updating and Installing Dependencies 179 | 180 | First, update Ubuntu itself by running 181 | 182 | ```bash 183 | (VM) $ sudo apt-get update 184 | ``` 185 | 186 | Then add in some dependencies for Ruby 187 | 188 | ```bash 189 | (VM) $ sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties 190 | ``` 191 | 192 | There are a few different ways to install Ruby. For this tutorial we're going to use [RVM](https://rvm.io/) 193 | 194 | ### Installing RVM 195 | 196 | First, install some dependencies required by RVM 197 | ```bash 198 | (VM) $ sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev 199 | ``` 200 | 201 | Next, retrieve RVM and install 202 | 203 | ```bash 204 | (VM) $ curl -L https://get.rvm.io | bash -s stable 205 | ``` 206 | 207 | NOTE: If you receive an error "gpg: Can't check signature: public key not found", run this command to install the required key 208 | ```bash 209 | (VM) $ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 210 | ``` 211 | 212 | Then re-run 213 | 214 | ```bash 215 | (VM) $ curl -L https://get.rvm.io | bash -s stable 216 | ``` 217 | 218 | ### Sourcing RVM 219 | Next, we need to source the rvm scripts directory and add it to the VM's .bashrc 220 | 221 | ```bash 222 | (VM) $ source ~/.rvm/scripts/rvm 223 | ``` 224 | 225 | ```bash 226 | (VM) $ echo "source ~/.rvm/scripts/rvm" >> ~/.bashrc 227 | ``` 228 | 229 | ### Installing Ruby 230 | 231 | First, we install Ruby 2.1.3 232 | ```bash 233 | (VM) $ rvm install 2.1.3 234 | ``` 235 | NOTE- don't worry if you see the message "Unknown ruby string (do not know how to handle): ruby-2.1.3." Wait a few seconds and see if the install continues, you should see the message "Searching for binary rubies, this might take some time." 236 | 237 | Next, we tell RVM to use 2.1.3 as the default Ruby 238 | ```bash 239 | (VM) $ rvm use 2.1.3 --default 240 | ``` 241 | 242 | And, finally, it's time to check the Ruby version. 243 | ```bash 244 | (VM) $ ruby -v 245 | ``` 246 | 247 | If everything is set up correctly, you should see this when you run the previous command 248 | ```bash 249 | (VM) $ ruby -v 250 | ruby 2.1.3p242 (2014-09-19 revision 47630) [x86_64-linux] 251 | ``` 252 | 253 | ## 4. Install Apache 254 | ```bash 255 | (VM) $ sudo apt-get install apache2 256 | ``` 257 | Next, we need to verify that Apache is working on the VM. To do this from the command line, run 258 | 259 | ```bash 260 | (VM) $ wget -qO- 127.0.0.1 261 | ``` 262 | 263 | If Apache is installed correctly, the command line will output an html document which includes the words "It works!" 264 | 265 | Now to verify that the VM can be accessed through a web browser. 266 | 267 | ### If you are using Vagrant 268 | 269 | At this point, even with Apache installed, we cannot access the VM in the browser. 270 | 271 | To fix this, open up your VagrantFile on your local machine with the editor of your choice (I use Vim) 272 | 273 | ```bash 274 | (Local) $ vim Vagrantfile 275 | ``` 276 | 277 | Locate this line in the Vagrantfile 278 | ```bash 279 | # config.vm.network "private_network", ip: "192.168.33.10" 280 | ``` 281 | 282 | Uncomment out that line so it looks like this 283 | ```bash 284 | config.vm.network "private_network", ip: "192.168.33.10" 285 | ``` 286 | 287 | This assigns an IP address to our Vagrant machine so we can access it in the web browser. 288 | 289 | Then save and quit the file. 290 | 291 | If your VM is still running, run this command to reload the configuration to include these changes. 292 | ```bash 293 | $ (Local) vagrant reload 294 | ``` 295 | 296 | Now, access "http://192.168.33.10" in a browser and you should see the Apache2 Ubuntu Default Page. It's a working web server! 297 | 298 | ## 5. Install Passenger 299 | 300 | Switch back to your VM. First, download and install the Passenger gem 301 | ```bash 302 | (VM) $ gem install passenger 303 | ``` 304 | 305 | Use this command to set up Passenger 306 | ```bash 307 | (VM) $ passenger-install-apache2-module 308 | ``` 309 | 310 | This will guide you through the set up. 311 | Make sure to select Ruby as a language you prefer. 312 | 313 | If the installer advises you to install additional packages, go ahead and install them. Then rerun 314 | ```bash 315 | (VM) $ passenger-install-apache2-module 316 | ``` 317 | 318 | If the installer advises you to add more swap memory, follow the directions to do this and re-run the installer again. 319 | 320 | Eventually, the installer will prompt you to add these lines to your Apache configuration file. Paste these into /etc/apache2/apache2.conf 321 | 322 | ```bash 323 | LoadModule passenger_module /home/deploy/.rvm/gems/ruby-2.1.3/gems/passenger-4.0.57/buildout/apache2/mod_passenger.so 324 | 325 | PassengerRoot /home/deploy/.rvm/gems/ruby-2.1.3/gems/passenger-4.0.57 326 | PassengerDefaultRuby /home/deploy/.rvm/gems/ruby-2.1.3/wrappers/ruby 327 | 328 | ``` 329 | 330 | Then restart Apache2 331 | ```bash 332 | (VM) $ sudo service apache2 restart 333 | ``` 334 | Finally, verify that passenger is running with this command: 335 | ```bash 336 | (VM) $ passenger-memory-stats 337 | ``` 338 | 339 | You should see a list of processes. 340 | 341 | ## 6. Install PostgreSQL 342 | 343 | Install PostgreSQL with: 344 | ```bash 345 | (VM) $ sudo apt-get install postgresql 346 | ``` 347 | 348 | By default, PostgreSQL will create a postgres user. Let's switch to this user. 349 | 350 | ```bash 351 | (VM) $ sudo -u postgres -s 352 | ``` 353 | 354 | Rather than using the postgres user all the time, we're going to create a deploy user our application will use to connect to the database. 355 | 356 | ```bash 357 | (VM) $ createuser deploy --pwprompt 358 | ``` 359 | 360 | Make sure to note the password, you will need it later when configuring your Rails application. 361 | 362 | Finally, exit out of the postgres user account. 363 | 364 | ```bash 365 | (VM) $ exit 366 | ``` 367 | 368 | Now, let's enter into Postgres and give the deploy user we just created permission to create a database. Start up Postgres with this command: 369 | 370 | ```bash 371 | (VM) $ sudo -u postgres psql postgres 372 | ``` 373 | 374 | When the psql prompt appears, enter this command: 375 | 376 | ```bash 377 | (VM) $ ALTER USER deploy CREATEDB; 378 | ``` 379 | 380 | 381 | And we now have a basic, working web server. To learn how to use Capistrano to deploy your application to this web server head on over the the next chapter! 382 | --------------------------------------------------------------------------------