├── 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 |
--------------------------------------------------------------------------------