orats 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +176 -41
- data/lib/orats/cli.rb +85 -35
- data/lib/orats/server.rb +3 -2
- data/lib/orats/shell.rb +83 -11
- data/lib/orats/templates/{commands/auth.rb → auth.rb} +0 -0
- data/lib/orats/templates/{commands/base.rb → base.rb} +1 -1
- data/lib/orats/templates/cook.rb +630 -0
- data/lib/orats/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a6c0e8dbdf731aa4475b5146b8e7816d42dd9db
|
4
|
+
data.tar.gz: 2574c41229f58b27670a7d6caff9af1a6b4cc2a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0629f4d2632b7697ea66880de7723762ac23714a110f770b4a221e22f7ac0d293eda935cc7e6a29b27179a3ca6dce448d1c5cdb7dfcc6d4b63e88f360c5cd3f
|
7
|
+
data.tar.gz: 30eaf60bafff537a7ed5931d15715addde4e548955286fedb51258e6af4135d4f71d79530933e205c947b9e4e89df0c286f3f0d2ed0455ac90a10e48fc29d1a6
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
orats (0.
|
4
|
+
orats (0.3.0)
|
5
5
|
thor (~> 0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
rake (
|
10
|
+
rake (0.9.6)
|
11
11
|
thor (0.18.1)
|
12
12
|
|
13
13
|
PLATFORMS
|
@@ -16,4 +16,4 @@ PLATFORMS
|
|
16
16
|
DEPENDENCIES
|
17
17
|
bundler (~> 1.5)
|
18
18
|
orats!
|
19
|
-
rake
|
19
|
+
rake (~> 0)
|
data/README.md
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
## What is orats and what problem does it solve?
|
2
2
|
|
3
|
-
It stands for opinionated rails application templates.
|
4
|
-
|
3
|
+
It stands for opinionated rails application templates. The templates include solving tedious tasks that you would do for most
|
4
|
+
projects. It handles creating a rails application with a bunch of opinions and optionally a chef cookbook so you can deploy
|
5
|
+
your app quickly.
|
5
6
|
|
6
|
-
|
7
|
-
setup all of this manually each time you make an app.
|
8
|
-
|
9
|
-
It is clearly a problem that can be automated so I sat down and started to create a few templates to do just that.
|
7
|
+
Everything is accessed through the [orats gem](#installation).
|
10
8
|
|
11
9
|
## What version of Rails and Ruby are you targeting?
|
12
10
|
|
@@ -15,14 +13,14 @@ It is clearly a problem that can be automated so I sat down and started to creat
|
|
15
13
|
I will be updating them as new versions come out and when the gems used are proven to work. All important gems in the Gemfile
|
16
14
|
are locked using the pessimistic operator `~>` so you can be sure that everything plays nice as long as rubygems.org is up!
|
17
15
|
|
18
|
-
## System dependencies that
|
16
|
+
## System dependencies that you must have on your dev box
|
19
17
|
|
20
18
|
- [The orats gem](#installation)
|
21
19
|
- To download each rails template and automate running certain tasks.
|
22
20
|
- Ruby 2.1.x
|
23
21
|
- Yep, you really need Ruby to run Ruby modules.
|
24
22
|
- Rails 4.0.x
|
25
|
-
- You
|
23
|
+
- You need Rails installed so that you can run the project generator.
|
26
24
|
- Git
|
27
25
|
- The weapon of choice for version control.
|
28
26
|
- Postgres
|
@@ -30,19 +28,34 @@ are locked using the pessimistic operator `~>` so you can be sure that everythin
|
|
30
28
|
- Redis
|
31
29
|
- Used as a sidekiq background worker and as the rails cache back end.
|
32
30
|
|
31
|
+
### Additional system dependencies for creating cookbooks
|
32
|
+
|
33
|
+
`orats` is smart enough to skip trying to create a cookbook if it cannot find the necessary dependencies to successfully
|
34
|
+
create the cookbook, but to successfully create a cookbook you must fulfil the requirements below:
|
35
|
+
|
36
|
+
- Chef is installed and setup in such a way that `knife` is on your system path.
|
37
|
+
- Berkshelf has been gem installed and you can run `berks` from anywhere.
|
38
|
+
|
39
|
+
Not sure what chef or berkshelf is? No problem, learn about chef from these resources:
|
40
|
+
|
41
|
+
- [Learn chef course](https://learnchef.opscode.com/)
|
42
|
+
- [Berkshelf readme](http://www.berkshelf.com/)
|
43
|
+
- [Berkshelf tutorial series](http://misheska.com/blog/2013/06/16/getting-started-writing-chef-cookbooks-the-berkshelf-way/)
|
44
|
+
|
33
45
|
## Contents
|
34
46
|
|
35
47
|
- orats
|
36
48
|
- [Installation](#installation)
|
37
49
|
- [Commands](#commands)
|
38
50
|
- Templates
|
39
|
-
- [Base](#base
|
51
|
+
- [Base](#base)
|
40
52
|
- [Authentication and authorization](#authentication-and-authorization)
|
41
|
-
- [
|
42
|
-
|
53
|
+
- [Cookbook](#cookbook)
|
54
|
+
- [Overview](#the-cookbook-comes-with-the-following-features)
|
43
55
|
- Sections
|
44
|
-
- [Expanding beyond the base template](#expanding-beyond-the-base-template)
|
45
56
|
- [Production tweaks](#production-tweaks)
|
57
|
+
- Wikis
|
58
|
+
- [Chef walk through](https://github.com/nickjj/orats/wiki/Chef-walk-through)
|
46
59
|
|
47
60
|
## orats
|
48
61
|
|
@@ -50,36 +63,38 @@ are locked using the pessimistic operator `~>` so you can be sure that everythin
|
|
50
63
|
|
51
64
|
`gem install orats`
|
52
65
|
|
53
|
-
|
54
66
|
### Commands
|
55
67
|
|
56
|
-
|
68
|
+
Here is an overview of the available commands. You can find out more information about each command and flag by simply
|
69
|
+
running `orats <command name> help` from your terminal. You can also type `orats` on its own to see a list of all commands.
|
57
70
|
|
58
|
-
- Create a new
|
59
|
-
- `orats
|
60
|
-
-
|
61
|
-
|
71
|
+
- Create a new orats project
|
72
|
+
- `orats new <APP_PATH> --pg-password <development postgres db password>`
|
73
|
+
- Configuration:
|
74
|
+
- Optionally takes: `--pg-location [localhost]`
|
75
|
+
- Optionally takes: `--pg-username [postgres]`
|
76
|
+
- Template features:
|
77
|
+
- Optionally takes: `--auth [false]`
|
78
|
+
- Project features:
|
79
|
+
- Optionally takes: `--skip-cook [false]`
|
80
|
+
- Optionally takes: `--skip-extras [false]`
|
62
81
|
|
63
|
-
- Create a
|
64
|
-
- `orats
|
65
|
-
- Optionally takes `--postgres-location [localhost]`
|
66
|
-
- Optionally takes `--postgres-username [postgres]`
|
82
|
+
- Create a stand alone chef cookbook
|
83
|
+
- `orats cook <APP_PATH>`
|
67
84
|
|
68
|
-
- Delete
|
69
|
-
- `orats nuke <
|
70
|
-
- Optionally takes `--
|
85
|
+
- Delete the directory and optionally all data associated to it
|
86
|
+
- `orats nuke <APP_PATH>`
|
87
|
+
- Optionally takes `--skip-data [false]`
|
71
88
|
|
72
89
|
#### Why is it asking me for my development postgres password?
|
73
90
|
|
74
|
-
The password is it asking for is only for your development database. It will **never** ask for your production passwords.
|
75
|
-
|
76
91
|
In order to automate certain tasks such as running database migrations the script must be able to talk to your database.
|
77
92
|
It cannot talk to your database without knowing the location, username and password for postgres. In most cases the
|
78
93
|
location will be `localhost` and the username will be `postgres` so these values are provided by default.
|
79
94
|
|
80
|
-
|
95
|
+
Remember, this is only your development postgres password. It will **never** ask for your production passwords.
|
81
96
|
|
82
|
-
## Base
|
97
|
+
## Base
|
83
98
|
|
84
99
|
This is the starter template that every other template will append to. I feel like when I make a new project, 95% of the time
|
85
100
|
it includes these features and when I do not want a specific thing it is much quicker to remove it than add it.
|
@@ -117,7 +132,20 @@ Everything has been added with proper git commits so you have a trail of changes
|
|
117
132
|
|
118
133
|
### Try it
|
119
134
|
|
120
|
-
`orats
|
135
|
+
`orats new myapp --pg-password <development postgres db password> -C`
|
136
|
+
|
137
|
+
*We are running the command with `-C` to ignore creating a cookbook so the installation is faster.*
|
138
|
+
|
139
|
+
#### What's with the services directory?
|
140
|
+
|
141
|
+
It is just a naming convention that I like to apply, you can name it whatever you want later or remove it with a flag. My thought
|
142
|
+
process was you might have multiple services which when put together create your web application. In many cases your web
|
143
|
+
application might just be a single rails app, but maybe not.
|
144
|
+
|
145
|
+
What if you introduced a Go service to do something which your rails application talks to for a certain area of your site?
|
146
|
+
Perhaps you have 2 rails applications too. One of them for your admin app and the other for the public facing app.
|
147
|
+
|
148
|
+
Long story short the extra directory is probably worth it in the long run and it's simple to remove if you don't like it.
|
121
149
|
|
122
150
|
### All I see is the default rails page
|
123
151
|
|
@@ -182,18 +210,125 @@ I feel like this is the cleanest way to disable registrations while still allowi
|
|
182
210
|
|
183
211
|
### Try it
|
184
212
|
|
185
|
-
`orats
|
213
|
+
`orats new myauthapp --pg-password <development postgres db password> --auth -C`
|
214
|
+
|
215
|
+
*We are running the command with `-C` to ignore creating a cookbook so the installation is faster.*
|
216
|
+
|
217
|
+
## Cookbook
|
218
|
+
|
219
|
+
Building your application is only one piece of the puzzle. If you want to ship your application you have to host it somewhere.
|
220
|
+
You have a few options when it comes to managed hosts like Heroku but they tend to be very expensive if you fall out of
|
221
|
+
their free tier.
|
222
|
+
|
223
|
+
The cookbook template creates a chef cookbook that will provision a **ubuntu 12.04 LTS server**. It can be hosted anywhere
|
224
|
+
as there are no hard requirements on any specific host. Chef is a server management framework. This template uses the
|
225
|
+
application cookbook pattern and depends on Berkshelf. Berkshelf is very similar to bundler but for chef cookbooks.
|
226
|
+
|
227
|
+
### The cookbook comes with the following features
|
228
|
+
|
229
|
+
- Security
|
230
|
+
- A random username is generated each time you generate a new cookbook.
|
231
|
+
- A random ssh port is generated each time you generate a new cookbook.
|
232
|
+
- Logging into the server is only possible with an SSH key.
|
233
|
+
- fail2ban is setup.
|
234
|
+
- ufw (firewall) is setup to block any ports not exposed.
|
235
|
+
- All stack specific processes are running with less privileges than root.
|
236
|
+
- Stack specific processes that are installed and configured
|
237
|
+
- Nginx
|
238
|
+
- Postgres
|
239
|
+
- Redis
|
240
|
+
- Runtimes
|
241
|
+
- Ruby 2.1.0 managed via rvm
|
242
|
+
- Nodejs 0.10.x
|
243
|
+
- Utils and features
|
244
|
+
- htop for emergency live monitoring
|
245
|
+
- logrotate with log rotation setup for anything that needs it.
|
246
|
+
- git
|
247
|
+
- A git repo in the deploy user's home directory which you can push to.
|
248
|
+
|
249
|
+
### Cookbook structure
|
250
|
+
|
251
|
+
It is broken up into 5 recipes:
|
252
|
+
|
253
|
+
- Base
|
254
|
+
- Database
|
255
|
+
- Cache
|
256
|
+
- Web
|
257
|
+
- Default
|
258
|
+
|
259
|
+
With the application style cookbook pattern it is a good idea to only run one recipe on your node. The default recipe
|
260
|
+
just composes the other 4 together. This makes it trivial to break out past one node in the future. If you wanted to
|
261
|
+
put your web server on server A and the database/cache servers on server B all you would have to do is create a new recipe
|
262
|
+
called something like `database_cache` (the name is arbitrary) and pull in both the database and cache recipes.
|
263
|
+
|
264
|
+
Then when you bootstrap the node you can tell it to use the new `database_cache` recipe. Awesome right? Yeah I know, chef rocks.
|
265
|
+
|
266
|
+
### Try it
|
267
|
+
|
268
|
+
`orats new mychefapp --pg-password <development postgres db password>`
|
269
|
+
|
270
|
+
#### Why is the cookbooks directory plural?
|
271
|
+
|
272
|
+
It is not uncommon for some projects to have multiple cookbooks. Of course that is completely out of scope for orats but
|
273
|
+
at least it generates a directory structure capable of sustaining multiple cookbooks.
|
274
|
+
|
275
|
+
### Tweakable attributes and meta data
|
276
|
+
|
277
|
+
You can quickly tweak a bunch of values by investigating the `attributes/default.rb` file. The values here are used in each
|
278
|
+
recipe. They are also namespaced to match the recipe file that uses them.
|
279
|
+
|
280
|
+
It is important that you change all of these values to match your setup. The only non-obvious one might be the SSH key. You
|
281
|
+
should use the key inside of your `.ssh/id_rsa.pub` file. It is the key that ends with your work station's username@hostname. Make
|
282
|
+
sure you do not include the trailing line break too.
|
283
|
+
|
284
|
+
You should also edit the details in the `metadata.rb` file.
|
285
|
+
|
286
|
+
### Encrypted values
|
287
|
+
|
288
|
+
Chef has this notion of encrypted data bags. They are used to protect sensitive information like passwords or secret tokens.
|
289
|
+
You can check out the `data_bags/<app_name>_secrets/production.json` file to know which fields you need to fill out later.
|
290
|
+
|
291
|
+
Please keep in mind that you should never input your real passwords/etc. in this file, it is only here to remind you which
|
292
|
+
settings are in your bag. This file is checked into version control. We will cover setting up the data bag with your real
|
293
|
+
information in [chef walk through on the wiki](https://github.com/nickjj/orats/wiki/Chef-walk-through).
|
294
|
+
|
295
|
+
### Workflow for customizing the cookbook
|
296
|
+
|
297
|
+
This cookbook is designed to be a generic base to get you started. It is highly encouraged to change the cookbook to suite your
|
298
|
+
exact needs. A typical workflow for making changes to the cookbook is this:
|
299
|
+
|
300
|
+
- Edit any files that you want to change.
|
301
|
+
- Bump the version in the `metadata.rb` file. *Never forget to do this step!*
|
302
|
+
- Run `berks upload` which sends the cookbooks up to your hosted chef server.
|
303
|
+
|
304
|
+
If you need to add new cookbooks then add them to `metadata.rb` and run `berks install`. If you need to pull in a cookbook
|
305
|
+
from a git repo or your local file system then put them in your `Berksfile` and also place them in `metadata.rb`. Check the
|
306
|
+
berkshelf documentation for more details.
|
307
|
+
|
308
|
+
#### Applying the cookbook changes on your server
|
309
|
+
|
310
|
+
This step is highly dependent but you have a few options. The first option is to ssh into your node and run `sudo chef-client`.
|
311
|
+
Replace ssh with capistrano if you want but the idea is the same. You would be manually invoking the `chef-client` command
|
312
|
+
which tells your node to contact the hosted chef server and pull in the changes.
|
313
|
+
|
314
|
+
The second option would be to setup a cronjob to run `chef-client` automatically at whatever interval you want. By default
|
315
|
+
I did not include this because by default chef does not do this.
|
316
|
+
|
317
|
+
Chef is idempotent so it will not re-run tasks that result in nothing changing so feel free to make changes whenever you
|
318
|
+
see fit.
|
319
|
+
|
320
|
+
### The server is up but how do I deploy my application?
|
186
321
|
|
187
|
-
|
322
|
+
This is another area where there are many options. You could use capistrano but you could also have chef manage the application
|
323
|
+
deployment too. I have a few old capistrano 2.x scripts that work fine and I really do not have any intentions of porting
|
324
|
+
them over to capistrano 3 scripts so they can be included as an orats template because I do not want to use capistrano anymore.
|
188
325
|
|
189
|
-
I
|
190
|
-
|
326
|
+
I'm calling out to the community for help. Can a chef expert please leverage the `deploy` or `application` resources
|
327
|
+
and provide us with a well documented solution to deploy a rails application with chef? Complete with runit scripts for
|
328
|
+
ensuring puma and sidekiq are always running of course.
|
191
329
|
|
192
|
-
|
193
|
-
dump out a ~200 line cookbook that configures everything to get a server up and running and all you would have to do is
|
194
|
-
change a few settings in the chef attributes file and setup an encrypted data bag like usual.
|
330
|
+
### Walk through
|
195
331
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
requests to add this functionality in.
|
332
|
+
If you have very little chef experience and want to go through the steps of creating a new orats project with a cookbook,
|
333
|
+
pushing it to a free managed chef server solution and bootstrapping a server on a local virtual machine then check out the
|
334
|
+
[chef walk through on the wiki](https://github.com/nickjj/orats/wiki/Chef-walk-through).
|
data/lib/orats/cli.rb
CHANGED
@@ -8,78 +8,128 @@ module Orats
|
|
8
8
|
include Shell
|
9
9
|
include Server
|
10
10
|
|
11
|
-
attr_accessor :
|
11
|
+
attr_accessor :active_path, :active_project
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
option :pg_location, default: 'localhost'
|
14
|
+
option :pg_username, default: 'postgres'
|
15
|
+
option :pg_password, required: true
|
16
|
+
option :auth, type: :boolean, default: false, aliases: '-a'
|
17
|
+
option :skip_cook, type: :boolean, default: false, aliases: '-C'
|
18
|
+
option :skip_extras, type: :boolean, default: false, aliases: '-E'
|
19
|
+
desc 'new APP_PATH [options]', ''
|
20
|
+
long_desc <<-LONGDESC
|
21
|
+
`orats new myapp --pg-password supersecret` will create a new orats project and it will also create a chef cookbook to go with it by default.
|
15
22
|
|
16
|
-
|
17
|
-
desc 'base APP_NAME', 'Create a new rails application using the base template.'
|
18
|
-
def base(app_name)
|
19
|
-
@app_name = app_name
|
23
|
+
You must supply at least this flag:
|
20
24
|
|
21
|
-
|
25
|
+
`--pg-password` to supply your development postgres password so the rails application can run database migrations
|
22
26
|
|
23
|
-
|
24
|
-
git_commit 'Change the postgres information'
|
27
|
+
Configuration:
|
25
28
|
|
26
|
-
|
27
|
-
git_commit 'Add gem lock file'
|
29
|
+
`--pg-location` to supply a custom postgres location [localhost]
|
28
30
|
|
29
|
-
|
30
|
-
git_commit 'Add the database schema file'
|
31
|
+
`--pg-username` to supply a custom postgres username [postgres]
|
31
32
|
|
32
|
-
|
33
|
-
|
33
|
+
Template features:
|
34
|
+
|
35
|
+
`--auth` will include authentication and authorization [false]
|
34
36
|
|
35
|
-
|
36
|
-
desc 'auth APP_NAME', 'Create a new rails application with authentication/authorization.'
|
37
|
-
def auth(app_name)
|
38
|
-
@app_name = app_name
|
37
|
+
Project features:
|
39
38
|
|
40
|
-
|
39
|
+
`--skip-cook` skip creating the cookbook [false]
|
41
40
|
|
42
|
-
|
41
|
+
`--skip-extras` skip creating the services directory and cookbook [false]
|
42
|
+
LONGDESC
|
43
|
+
def new(app_name)
|
44
|
+
@options = options
|
45
|
+
@active_path = app_name
|
43
46
|
|
44
|
-
|
47
|
+
@active_path = services_path(app_name)
|
48
|
+
rails_template 'base' do
|
49
|
+
gsub_postgres_info
|
50
|
+
|
51
|
+
bundle_install
|
52
|
+
git_commit 'Change the postgres information'
|
53
|
+
git_commit 'Add gem lock file'
|
54
|
+
|
55
|
+
run_rake 'db:create:all db:migrate db:test:prepare'
|
56
|
+
git_commit 'Add the database schema file'
|
57
|
+
end
|
58
|
+
|
59
|
+
if options[:auth]
|
60
|
+
rails_template 'auth', '--skip ' do
|
61
|
+
run_rake 'db:migrate db:seed'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
unless options[:skip_cook] || options[:skip_extras]
|
66
|
+
cook_app cookbooks_path(app_name)
|
67
|
+
end
|
45
68
|
|
69
|
+
@active_path = services_path(app_name)
|
46
70
|
foreman_start unless invoked?
|
47
71
|
end
|
48
72
|
|
49
|
-
desc '
|
50
|
-
|
51
|
-
|
73
|
+
desc 'cook APP_PATH', ''
|
74
|
+
long_desc <<-LONGDESC
|
75
|
+
`orats cook myapp` will create a stand alone cookbook.
|
76
|
+
LONGDESC
|
77
|
+
def cook(app_name)
|
78
|
+
@options = options
|
79
|
+
@active_path = app_name
|
80
|
+
|
81
|
+
cook_app app_name
|
82
|
+
end
|
83
|
+
|
84
|
+
option :skip_data, type: :boolean, default: false, aliases: '-S'
|
85
|
+
desc 'nuke APP_PATH [options]', ''
|
86
|
+
long_desc <<-LONGDESC
|
87
|
+
`orats nuke myapp` will delete the directory and optionally all data associated to it.
|
88
|
+
|
89
|
+
Options:
|
90
|
+
|
91
|
+
`--skip-data` will skip deleting app specific postgres databases and redis namespaces [false]
|
92
|
+
LONGDESC
|
52
93
|
def nuke(app_name)
|
53
|
-
@
|
94
|
+
@active_path = app_name
|
54
95
|
|
55
96
|
puts
|
56
97
|
say_status 'nuke', "\e[1mYou are about to permanently delete this directory:\e[0m", :red
|
57
|
-
say_status 'path', "#{File.expand_path(
|
98
|
+
say_status 'path', "#{File.expand_path(@active_path)}", :yellow
|
58
99
|
|
59
|
-
|
100
|
+
unless options[:skip_data]
|
60
101
|
puts
|
61
102
|
say_status 'nuke', "\e[1mYou are about to permanently delete these postgres databases:\e[0m", :red
|
62
|
-
say_status 'databases', "#{
|
103
|
+
say_status 'databases', "#{active_project} and #{active_project}_test", :yellow
|
63
104
|
puts
|
64
105
|
say_status 'nuke', "\e[1mYou are about to permanently delete this redis namespace:\e[0m", :red
|
65
|
-
say_status 'namespace',
|
106
|
+
say_status 'namespace', active_project, :yellow
|
66
107
|
end
|
67
108
|
puts
|
68
109
|
|
69
110
|
confirmed_to_delete = yes?('Are you sure? (y/N)', :cyan)
|
70
111
|
|
71
112
|
if confirmed_to_delete
|
72
|
-
|
113
|
+
unless options[:skip_data]
|
73
114
|
run_rake 'db:drop:all'
|
74
115
|
nuke_redis
|
75
|
-
nuke_directory
|
76
116
|
end
|
117
|
+
|
118
|
+
nuke_directory
|
77
119
|
end
|
78
120
|
end
|
79
121
|
|
80
122
|
private
|
81
|
-
def
|
82
|
-
@
|
123
|
+
def active_project
|
124
|
+
@active_path.split('/').last
|
125
|
+
end
|
126
|
+
|
127
|
+
def services_path(app_name)
|
128
|
+
options[:skip_extras] ? app_name : "#{app_name}/services/#{active_project}"
|
129
|
+
end
|
130
|
+
|
131
|
+
def cookbooks_path(app_name)
|
132
|
+
"#{app_name}/cookbooks/#{active_project}"
|
83
133
|
end
|
84
134
|
|
85
135
|
def invoked?
|
data/lib/orats/server.rb
CHANGED
@@ -6,7 +6,7 @@ module Orats
|
|
6
6
|
def foreman_start
|
7
7
|
puts '', '='*80
|
8
8
|
say_status 'action', "\e[1mStarting server with the following commands:\e[0m", :cyan
|
9
|
-
say_status 'command', "cd #{@
|
9
|
+
say_status 'command', "cd #{@active_path}", :magenta
|
10
10
|
say_status 'command', 'bundle exec foreman start', :magenta
|
11
11
|
puts '='*80, ''
|
12
12
|
|
@@ -25,7 +25,8 @@ module Orats
|
|
25
25
|
end
|
26
26
|
|
27
27
|
puts
|
28
|
-
|
28
|
+
|
29
|
+
run_from @active_path, 'bundle exec foreman start'
|
29
30
|
end
|
30
31
|
|
31
32
|
def port_taken?
|
data/lib/orats/shell.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
module Orats
|
2
2
|
module Shell
|
3
|
-
def
|
4
|
-
run "cd #{
|
3
|
+
def run_from(path, command)
|
4
|
+
run "cd #{path} && #{command} && cd -"
|
5
|
+
end
|
6
|
+
|
7
|
+
def cd_inside(path, &block)
|
8
|
+
run "cd #{path}"
|
9
|
+
yield
|
10
|
+
run 'cd -'
|
5
11
|
end
|
6
12
|
|
7
13
|
def log_message(type, message)
|
@@ -11,39 +17,105 @@ module Orats
|
|
11
17
|
end
|
12
18
|
|
13
19
|
def git_commit(message)
|
14
|
-
|
20
|
+
run_from @active_path, "git add . && git commit -m '#{message}'"
|
15
21
|
end
|
16
22
|
|
17
|
-
def gsub_postgres_info
|
23
|
+
def gsub_postgres_info
|
18
24
|
log_message 'root', 'Changing the postgres information'
|
19
25
|
|
20
|
-
gsub_file "#{@
|
21
|
-
gsub_file "#{@
|
22
|
-
gsub_file "#{@
|
26
|
+
gsub_file "#{@active_path}/.env", ': localhost', ": #{@options[:pg_location]}"
|
27
|
+
gsub_file "#{@active_path}/.env", ': postgres', ": #{@options[:pg_username]}"
|
28
|
+
gsub_file "#{@active_path}/.env", ': supersecrets', ": #{@options[:pg_password]}"
|
23
29
|
end
|
24
30
|
|
25
31
|
def run_rake(command)
|
26
32
|
log_message 'shell', 'Running rake commands'
|
27
33
|
|
28
|
-
|
34
|
+
run_from @active_path, "bundle exec rake #{command}"
|
29
35
|
end
|
30
36
|
|
31
37
|
def bundle_install
|
32
38
|
log_message 'shell', 'Running bundle install, this may take a while'
|
33
39
|
|
34
|
-
|
40
|
+
run_from @active_path, 'bundle install'
|
35
41
|
end
|
36
42
|
|
37
43
|
def nuke_redis
|
38
44
|
log_message 'root', 'Removing redis keys'
|
39
45
|
|
40
|
-
run "redis-cli KEYS '#{
|
46
|
+
run "redis-cli KEYS '#{active_project}:*' | xargs --delim='\n' redis-cli DEL"
|
41
47
|
end
|
42
48
|
|
43
49
|
def nuke_directory
|
44
50
|
log_message 'root', 'Deleting directory'
|
45
51
|
|
46
|
-
run "rm -rf #{@
|
52
|
+
run "rm -rf #{@active_path}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def exit_if_exists
|
56
|
+
log_message 'shell', 'Checking if a file or directory already exists'
|
57
|
+
|
58
|
+
if Dir.exist?(@active_path) || File.exist?(@active_path)
|
59
|
+
puts
|
60
|
+
say_status 'aborting', "\e[1mA file or directory already exists at this location:\e[0m", :red
|
61
|
+
say_status 'location', @active_path, :yellow
|
62
|
+
puts '-'*80
|
63
|
+
puts
|
64
|
+
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def exit_if_cannot_cook
|
70
|
+
log_message 'shell', 'Checking for the cookbook system dependencies'
|
71
|
+
|
72
|
+
has_knife = run('which knife', capture: true)
|
73
|
+
has_berks = run('which berks', capture: true)
|
74
|
+
|
75
|
+
dependency_error 'Cannot access knife',
|
76
|
+
'Are you sure you have chef setup correctly?',
|
77
|
+
'http://www.getchef.com/chef/install/`' if has_knife.empty?
|
78
|
+
|
79
|
+
|
80
|
+
dependency_error 'Cannot access berkshelf',
|
81
|
+
'Are you sure you have berkshelf installed correctly?',
|
82
|
+
'You can install it by running `gem install berkshelf`' if has_berks.empty?
|
83
|
+
end
|
84
|
+
|
85
|
+
def exit_if_cannot_rails
|
86
|
+
log_message 'shell', 'Checking for rails'
|
87
|
+
|
88
|
+
has_rails = run('which rails', capture: true)
|
89
|
+
|
90
|
+
dependency_error 'Cannot access rails',
|
91
|
+
'Are you sure you have rails setup correctly?',
|
92
|
+
'You can install it by running `gem install rails`' if has_rails.empty?
|
93
|
+
end
|
94
|
+
|
95
|
+
def dependency_error(message, question, answer)
|
96
|
+
puts
|
97
|
+
say_status 'error', "\e[1m#{message}\e[0m", :red
|
98
|
+
say_status 'question', question, :yellow
|
99
|
+
say_status 'answer', answer, :cyan
|
100
|
+
puts '-'*80
|
101
|
+
puts
|
102
|
+
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
|
106
|
+
def rails_template(command, flags = '', &block)
|
107
|
+
exit_if_cannot_rails
|
108
|
+
exit_if_exists unless flags.index(/--skip /)
|
109
|
+
|
110
|
+
run "rails new #{@active_path} #{flags}--skip-bundle --template #{File.expand_path File.dirname(__FILE__)}/templates/#{command}.rb"
|
111
|
+
yield if block_given?
|
112
|
+
end
|
113
|
+
|
114
|
+
def cook_app(app_path)
|
115
|
+
exit_if_cannot_cook
|
116
|
+
|
117
|
+
@active_path = app_path
|
118
|
+
rails_template 'cook'
|
47
119
|
end
|
48
120
|
end
|
49
121
|
end
|
File without changes
|
@@ -11,7 +11,7 @@ def generate_token
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def from_gem(source, destination = nil)
|
14
|
-
base_path = "#{File.expand_path File.dirname(__FILE__)}
|
14
|
+
base_path = "#{File.expand_path File.dirname(__FILE__)}/includes"
|
15
15
|
file_name = source.split('/').last
|
16
16
|
|
17
17
|
if destination.present? && file_name != destination
|
@@ -0,0 +1,630 @@
|
|
1
|
+
# =====================================================================================================
|
2
|
+
# Template for generating a chef cookbook
|
3
|
+
# =====================================================================================================
|
4
|
+
|
5
|
+
# ----- Helper functions and variables ----------------------------------------------------------------
|
6
|
+
|
7
|
+
require 'securerandom'
|
8
|
+
|
9
|
+
def generate_token
|
10
|
+
SecureRandom.hex(64)
|
11
|
+
end
|
12
|
+
|
13
|
+
def git_config(field)
|
14
|
+
command = "git config --global user.#{field}"
|
15
|
+
git_field_value = run(command, capture: true).gsub("\n", '')
|
16
|
+
default_value = "YOUR_#{field.upcase}"
|
17
|
+
|
18
|
+
git_field_value.to_s.empty? ? default_value : git_field_value
|
19
|
+
end
|
20
|
+
|
21
|
+
app_name_upper = app_name.upcase
|
22
|
+
app_name_class = app_name.humanize
|
23
|
+
|
24
|
+
author_name = git_config 'name'
|
25
|
+
author_email = git_config 'email'
|
26
|
+
|
27
|
+
# ----- Nuke all of the rails code --------------------------------------------------------------------
|
28
|
+
|
29
|
+
puts
|
30
|
+
say_status 'shell', 'Removing all of the generated rails code...', :yellow
|
31
|
+
puts '-'*80, ''; sleep 0.25
|
32
|
+
|
33
|
+
run 'rm -rf * .git .gitignore'
|
34
|
+
|
35
|
+
# ----- Install berkshelf -----------------------------------------------------------------------------
|
36
|
+
|
37
|
+
puts
|
38
|
+
say_status 'tool', 'Gem installing berkshelf, this may take a while...', :yellow
|
39
|
+
puts '-'*80, ''; sleep 0.25
|
40
|
+
|
41
|
+
run 'gem install berkshelf'
|
42
|
+
|
43
|
+
# ----- Create cookbook -------------------------------------------------------------------------------
|
44
|
+
|
45
|
+
puts
|
46
|
+
say_status 'init', 'Creating skeleton cookbook...', :yellow
|
47
|
+
puts '-'*80, ''; sleep 0.25
|
48
|
+
|
49
|
+
run "berks cookbook #{app_name}"
|
50
|
+
|
51
|
+
# ----- Move cookbook back one directory --------------------------------------------------------------
|
52
|
+
|
53
|
+
puts
|
54
|
+
say_status 'shell', 'Moving cookbook back one directory...', :yellow
|
55
|
+
puts '-'*80, ''; sleep 0.25
|
56
|
+
|
57
|
+
run "mv #{app_name}/* ."
|
58
|
+
run "rm -rf #{app_name}"
|
59
|
+
|
60
|
+
# ----- Create the git repo ---------------------------------------------------------------------------
|
61
|
+
|
62
|
+
puts
|
63
|
+
say_status 'git', 'Creating initial commit...', :yellow
|
64
|
+
puts '-'*80, ''; sleep 0.25
|
65
|
+
|
66
|
+
git :init
|
67
|
+
git add: '.'
|
68
|
+
git commit: "-m 'Initial commit'"
|
69
|
+
|
70
|
+
# ----- Create the license ----------------------------------------------------------------------------
|
71
|
+
|
72
|
+
puts
|
73
|
+
say_status 'root', 'Creating the license', :yellow
|
74
|
+
puts '-'*80, ''; sleep 0.25
|
75
|
+
|
76
|
+
run 'rm -rf LICENSE'
|
77
|
+
|
78
|
+
file 'LICENSE' do <<-TEXT
|
79
|
+
The MIT License (MIT)
|
80
|
+
|
81
|
+
Copyright (c) #{Time.now.year} #{author_name} <#{author_email}>
|
82
|
+
|
83
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
84
|
+
a copy of this software and associated documentation files (the
|
85
|
+
'Software'), to deal in the Software without restriction, including
|
86
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
87
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
88
|
+
permit persons to whom the Software is furnished to do so, subject to
|
89
|
+
the following conditions:
|
90
|
+
|
91
|
+
The above copyright notice and this permission notice shall be
|
92
|
+
included in all copies or substantial portions of the Software.
|
93
|
+
|
94
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
95
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
96
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
97
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
98
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
99
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
100
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
101
|
+
TEXT
|
102
|
+
end
|
103
|
+
|
104
|
+
git add: '.'
|
105
|
+
git commit: "-m 'Add MIT license'"
|
106
|
+
|
107
|
+
# ----- Customize meta data ---------------------------------------------------------------------------
|
108
|
+
|
109
|
+
puts
|
110
|
+
say_status 'root', 'Changing metadata file', :yellow
|
111
|
+
puts '-'*80, ''; sleep 0.25
|
112
|
+
|
113
|
+
puts author_name
|
114
|
+
puts author_email
|
115
|
+
|
116
|
+
gsub_file 'metadata.rb', 'YOUR_NAME', author_name
|
117
|
+
gsub_file 'metadata.rb', 'YOUR_EMAIL', author_email
|
118
|
+
gsub_file 'metadata.rb', 'All rights reserved', 'MIT LICENSE'
|
119
|
+
|
120
|
+
git add: '.'
|
121
|
+
git commit: "-m 'Change meta data in the metadata.rb file'"
|
122
|
+
|
123
|
+
# ----- Add application dependencies ------------------------------------------------------------------
|
124
|
+
|
125
|
+
puts
|
126
|
+
say_status 'root', 'Adding application dependencies...', :yellow
|
127
|
+
puts '-'*80, ''; sleep 0.25
|
128
|
+
|
129
|
+
append_file 'Berksfile' do <<-CODE
|
130
|
+
cookbook 'postgresql', git: 'git://github.com/phlipper/chef-postgresql.git'
|
131
|
+
cookbook 'rvm', git: 'git://github.com/fnichol/chef-rvm'
|
132
|
+
CODE
|
133
|
+
end
|
134
|
+
|
135
|
+
git add: '.'
|
136
|
+
git commit: "-m 'Add dependencies to the Berksfile'"
|
137
|
+
|
138
|
+
append_file 'metadata.rb' do <<-CODE
|
139
|
+
# base
|
140
|
+
depends 'openssh', '~> 1.3.2'
|
141
|
+
depends 'user', '~> 0.3.0'
|
142
|
+
depends 'sudo', '~> 2.3.0'
|
143
|
+
depends 'fail2ban', '~> 2.1.2'
|
144
|
+
depends 'ufw', '~> 0.7.4'
|
145
|
+
depends 'swap', '~> 0.3.6'
|
146
|
+
|
147
|
+
# database
|
148
|
+
depends 'postgresql', '~> 0.13.0'
|
149
|
+
|
150
|
+
# cache
|
151
|
+
depends 'redisio', '~> 1.7.0'
|
152
|
+
|
153
|
+
# web
|
154
|
+
depends 'git', '~> 2.9.0'
|
155
|
+
depends 'rvm', '~> 0.9.1'
|
156
|
+
depends 'nodejs', '~> 1.3.0'
|
157
|
+
depends 'nginx', '~> 2.2.0'
|
158
|
+
depends 'logrotate', '~> 1.4.0'
|
159
|
+
CODE
|
160
|
+
end
|
161
|
+
|
162
|
+
git add: '.'
|
163
|
+
git commit: "-m 'Add dependencies to the metadata file'"
|
164
|
+
|
165
|
+
# ----- Install cookbooks locally ---------------------------------------------------------------------
|
166
|
+
|
167
|
+
puts
|
168
|
+
say_status 'tool', 'Berks installing the cookbooks, this may take a while...', :yellow
|
169
|
+
puts '-'*80, ''; sleep 0.25
|
170
|
+
|
171
|
+
run 'berks install'
|
172
|
+
|
173
|
+
git add: '.'
|
174
|
+
git commit: "-m 'Change meta data in the metadata.rb file'"
|
175
|
+
|
176
|
+
# ----- Configure attributes file ---------------------------------------------------------------------
|
177
|
+
|
178
|
+
puts
|
179
|
+
say_status 'attr', 'Modifying the attributes file...', :yellow
|
180
|
+
puts '-'*80, ''; sleep 0.25
|
181
|
+
|
182
|
+
random_ssh_port = rand(11000..55000)
|
183
|
+
random_username = SecureRandom.hex[0...8]
|
184
|
+
|
185
|
+
file 'attributes/default.rb' do <<-CODE
|
186
|
+
default[:#{app_name}][:base][:ssh_port] = '#{random_ssh_port}'
|
187
|
+
default[:#{app_name}][:base][:username] = '#{random_username}'
|
188
|
+
default[:#{app_name}][:base][:swap_size] = 1024 # MBs
|
189
|
+
default[:#{app_name}][:base][:ssh_key] = 'INSERT_YOUR_PUBLIC_SSH_KEY_HERE'
|
190
|
+
|
191
|
+
default[:#{app_name}][:database][:host] = 'localhost'
|
192
|
+
default[:#{app_name}][:database][:pool] = '25'
|
193
|
+
default[:#{app_name}][:database][:timeout] = '5000'
|
194
|
+
|
195
|
+
default[:#{app_name}][:cache][:host] = 'localhost'
|
196
|
+
default[:#{app_name}][:cache][:port] = '6379'
|
197
|
+
default[:#{app_name}][:cache][:database] = '0'
|
198
|
+
default[:#{app_name}][:cache][:sidekiq_concurrency] = '25'
|
199
|
+
|
200
|
+
default[:#{app_name}][:web][:ruby_version] = '2.1.0'
|
201
|
+
default[:#{app_name}][:web][:puma_threads_min] = '0'
|
202
|
+
default[:#{app_name}][:web][:puma_threads_max] = '16'
|
203
|
+
default[:#{app_name}][:web][:puma_workers] = '2'
|
204
|
+
default[:#{app_name}][:web][:mail_address] = 'smtp.#{app_name}.com'
|
205
|
+
default[:#{app_name}][:web][:mail_port] = '25'
|
206
|
+
default[:#{app_name}][:web][:mail_domain] = '#{app_name}.com'
|
207
|
+
default[:#{app_name}][:web][:mail_username] = 'info@#{app_name}.com'
|
208
|
+
default[:#{app_name}][:web][:mail_auth] = 'plain'
|
209
|
+
default[:#{app_name}][:web][:mail_startttls_auto] = 'true'
|
210
|
+
default[:#{app_name}][:web][:action_mailer_host] = 'www.#{app_name}.com'
|
211
|
+
default[:#{app_name}][:web][:action_mailer_default_email] = 'info@#{app_name}.com'
|
212
|
+
default[:#{app_name}][:web][:action_mailer_devise_default_email] = 'info@#{app_name}.com'
|
213
|
+
CODE
|
214
|
+
end
|
215
|
+
|
216
|
+
git add: '.'
|
217
|
+
git commit: "-m 'Add tweakable settings to the attributes file'"
|
218
|
+
|
219
|
+
# ----- Create dummy data for the encrypted data bag --------------------------------------------------
|
220
|
+
|
221
|
+
puts
|
222
|
+
say_status 'data_bags', 'Creating dummy encrypted data bag...', :yellow
|
223
|
+
puts '-'*80, ''; sleep 0.25
|
224
|
+
|
225
|
+
data_bag_path = "data_bags/#{app_name}_secrets"
|
226
|
+
|
227
|
+
run "mkdir -p #{data_bag_path}"
|
228
|
+
|
229
|
+
file "#{data_bag_path}/production.json" do <<-JSON
|
230
|
+
{
|
231
|
+
"id": "production",
|
232
|
+
"database_password": "<real password is protected>",
|
233
|
+
"cache_password": "<real password is protected>",
|
234
|
+
"mail_password": "<real password is protected>",
|
235
|
+
"token_rails_secret": "<real token is protected>",
|
236
|
+
"token_devise_secret": "<real token is protected>",
|
237
|
+
"token_devise_pepper": "<real token is protected>"
|
238
|
+
}
|
239
|
+
JSON
|
240
|
+
end
|
241
|
+
|
242
|
+
git add: '.'
|
243
|
+
git commit: "-m 'Add the dummy data bag as a point of reference'"
|
244
|
+
|
245
|
+
# ----- Create nginx config ---------------------------------------------------------------------------
|
246
|
+
|
247
|
+
puts
|
248
|
+
say_status 'files', 'Creating nginx config...', :yellow
|
249
|
+
puts '-'*80, ''; sleep 0.25
|
250
|
+
|
251
|
+
file "files/default/nginx_virtualhost.conf" do <<-CONF
|
252
|
+
upstream #{app_name} {
|
253
|
+
server unix:///tmp/#{app_name}.sock;
|
254
|
+
}
|
255
|
+
|
256
|
+
# redirect non-www to www (remove this block if you do not want to do this)
|
257
|
+
server {
|
258
|
+
listen 80;
|
259
|
+
server_name #{app_name}.com;
|
260
|
+
return 301 $scheme://www.#{app_name}.com$request_uri;
|
261
|
+
}
|
262
|
+
|
263
|
+
server {
|
264
|
+
listen 80;
|
265
|
+
server_name www.#{app_name}.com;
|
266
|
+
root /home/#{random_username}/www/#{app_name}/current/public;
|
267
|
+
|
268
|
+
error_page 404 /404.html;
|
269
|
+
error_page 500 /500.html;
|
270
|
+
error_page 502 503 504 /502.html;
|
271
|
+
|
272
|
+
location ~ ^/(system|assets)/ {
|
273
|
+
root /home/#{random_username}/www/#{app_name}/current/public;
|
274
|
+
gzip_static on;
|
275
|
+
expires 1y;
|
276
|
+
add_header Cache-Control public;
|
277
|
+
add_header ETag "";
|
278
|
+
break;
|
279
|
+
}
|
280
|
+
|
281
|
+
try_files $uri @puma;
|
282
|
+
|
283
|
+
location @puma {
|
284
|
+
proxy_set_header X-Real-IP $remote_addr;
|
285
|
+
proxy_set_header X-Forwarded-Proto http;
|
286
|
+
proxy_set_header Host $http_host;
|
287
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
288
|
+
proxy_redirect off;
|
289
|
+
|
290
|
+
proxy_pass http://#{app_name};
|
291
|
+
break;
|
292
|
+
}
|
293
|
+
}
|
294
|
+
CONF
|
295
|
+
end
|
296
|
+
|
297
|
+
git add: '.'
|
298
|
+
git commit: "-m 'Add the nginx virtualhost config'"
|
299
|
+
|
300
|
+
# ----- Create system wide profile -------------------------------------------------------------------------
|
301
|
+
|
302
|
+
puts
|
303
|
+
say_status 'templates', 'Creating system wide profile config', :yellow
|
304
|
+
puts '-'*80, ''; sleep 0.25
|
305
|
+
|
306
|
+
file 'templates/default/profile.erb' do <<-CONF
|
307
|
+
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
|
308
|
+
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
|
309
|
+
|
310
|
+
if [ "$PS1" ]; then
|
311
|
+
if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then
|
312
|
+
# The file bash.bashrc already sets the default PS1.
|
313
|
+
# PS1='\h:\w\$ '
|
314
|
+
if [ -f /etc/bash.bashrc ]; then
|
315
|
+
. /etc/bash.bashrc
|
316
|
+
fi
|
317
|
+
else
|
318
|
+
if [ "`id -u`" -eq 0 ]; then
|
319
|
+
PS1='# '
|
320
|
+
else
|
321
|
+
PS1='$ '
|
322
|
+
fi
|
323
|
+
fi
|
324
|
+
fi
|
325
|
+
|
326
|
+
# The default umask is now handled by pam_umask.
|
327
|
+
# See pam_umask(8) and /etc/login.defs.
|
328
|
+
|
329
|
+
if [ -d /etc/profile.d ]; then
|
330
|
+
for i in /etc/profile.d/*.sh; do
|
331
|
+
if [ -r $i ]; then
|
332
|
+
. $i
|
333
|
+
fi
|
334
|
+
done
|
335
|
+
unset i
|
336
|
+
fi
|
337
|
+
|
338
|
+
export <%= @cookbook_name.upcase %>_TOKEN_RAILS_SECRET='<%= @token_rails_secret %>'
|
339
|
+
export <%= @cookbook_name.upcase %>_TOKEN_DEVISE_SECRET='<%= @token_devise_secret %>'
|
340
|
+
export <%= @cookbook_name.upcase %>_TOKEN_DEVISE_PEPPER='<%= @token_devise_pepper %>'
|
341
|
+
|
342
|
+
export <%= @cookbook_name.upcase %>_SMTP_ADDRESS='<%= node[:#{app_name}][:web][:mail_address] %>'
|
343
|
+
export <%= @cookbook_name.upcase %>_SMTP_PORT='<%= node[:#{app_name}][:web][:mail_port] %>'
|
344
|
+
export <%= @cookbook_name.upcase %>_SMTP_DOMAIN='<%= node[:#{app_name}][:web][:mail_domain] %>'
|
345
|
+
export <%= @cookbook_name.upcase %>_SMTP_USERNAME='<%= node[:#{app_name}][:web][:mail_username] %>'
|
346
|
+
export <%= @cookbook_name.upcase %>_SMTP_PASSWORD='<%= @mail_password %>'
|
347
|
+
export <%= @cookbook_name.upcase %>_SMTP_AUTH='<%= node[:#{app_name}][:web][:mail_auth] %>'
|
348
|
+
export <%= @cookbook_name.upcase %>_SMTP_STARTTTLS_AUTO='<%= node[:#{app_name}][:web][:mail_startttls_auto] %>'
|
349
|
+
|
350
|
+
export <%= @cookbook_name.upcase %>_ACTION_MAILER_HOST='<%= node[:#{app_name}][:web][:action_mailer_host] %>'
|
351
|
+
export <%= @cookbook_name.upcase %>_ACTION_MAILER_DEFAULT_EMAIL='<%= node[:#{app_name}][:web][:action_mailer_default_email] %>'
|
352
|
+
export <%= @cookbook_name.upcase %>_ACTION_MAILER_DEVISE_DEFAULT_EMAIL='<%= node[:#{app_name}][:web][:action_mailer_devise_default_email] %>'
|
353
|
+
|
354
|
+
export <%= @cookbook_name.upcase %>_DATABASE_HOST='<%= node[:#{app_name}][:database][:host] %>'
|
355
|
+
export <%= @cookbook_name.upcase %>_DATABASE_NAME='<%= @cookbook_name.downcase %>'
|
356
|
+
export <%= @cookbook_name.upcase %>_DATABASE_USERNAME='postgres'
|
357
|
+
export <%= @cookbook_name.upcase %>_DATABASE_PASSWORD='<%= @database_password %>'
|
358
|
+
export <%= @cookbook_name.upcase %>_DATABASE_POOL='<%= node[:#{app_name}][:database][:pool] %>'
|
359
|
+
export <%= @cookbook_name.upcase %>_DATABASE_TIMEOUT='<%= node[:#{app_name}][:database][:timeout] %>'
|
360
|
+
|
361
|
+
export <%= @cookbook_name.upcase %>_CACHE_HOST='<%= node[:#{app_name}][:cache][:host] %>'
|
362
|
+
export <%= @cookbook_name.upcase %>_CACHE_DATABASE='<%= node[:#{app_name}][:cache][:database] %>'
|
363
|
+
export <%= @cookbook_name.upcase %>_CACHE_USERNAME='redis'
|
364
|
+
export <%= @cookbook_name.upcase %>_CACHE_PASSWORD='<%= @cache_password %>'
|
365
|
+
|
366
|
+
export <%= @cookbook_name.upcase %>_SIDEKIQ_CONCURRENCY='<%= node[:#{app_name}][:cache][:sidekiq_concurrency] %>'
|
367
|
+
|
368
|
+
export <%= @cookbook_name.upcase %>_PUMA_THREADS_MIN='<%= node[:#{app_name}][:web][:puma_threads_min] %>'
|
369
|
+
export <%= @cookbook_name.upcase %>_PUMA_THREADS_MAX='<%= node[:#{app_name}][:web][:puma_threads_max] %>'
|
370
|
+
export <%= @cookbook_name.upcase %>_PUMA_WORKERS='<%= node[:#{app_name}][:web][:puma_workers] %>'
|
371
|
+
CONF
|
372
|
+
end
|
373
|
+
|
374
|
+
git add: '.'
|
375
|
+
git commit: "-m 'Add the system wide profile config'"
|
376
|
+
|
377
|
+
# ----- Create base recipe ----------------------------------------------------------------------------
|
378
|
+
|
379
|
+
puts
|
380
|
+
say_status 'recipes', 'Creating base recipe...', :yellow
|
381
|
+
puts '-'*80, ''; sleep 0.25
|
382
|
+
|
383
|
+
file 'recipes/base.rb' do <<-'CODE'
|
384
|
+
# openssh
|
385
|
+
|
386
|
+
node.override[:openssh][:server][:port] = node[:app_name][:base][:ssh_port]
|
387
|
+
node.override[:openssh][:server][:password_authentication] = 'no'
|
388
|
+
node.override[:openssh][:server][:permit_root_login] = 'no'
|
389
|
+
include_recipe 'openssh'
|
390
|
+
|
391
|
+
# user
|
392
|
+
|
393
|
+
include_recipe 'user'
|
394
|
+
|
395
|
+
user_account node[:app_name][:base][:username] do
|
396
|
+
ssh_keys [ node[:app_name][:base][:ssh_key] ]
|
397
|
+
end
|
398
|
+
|
399
|
+
# sudo
|
400
|
+
|
401
|
+
node.override[:authorization][:sudo][:users] = [ node[:app_name][:base][:username] ]
|
402
|
+
node.override[:authorization][:sudo][:passwordless] = true
|
403
|
+
|
404
|
+
include_recipe 'sudo'
|
405
|
+
|
406
|
+
# fail2ban
|
407
|
+
|
408
|
+
include_recipe 'fail2ban'
|
409
|
+
|
410
|
+
# ufw
|
411
|
+
|
412
|
+
node.override[:firewall][:rules] = [
|
413
|
+
{
|
414
|
+
'ssh' => {
|
415
|
+
'port'=> node[:app_name][:base][:ssh_port]
|
416
|
+
}
|
417
|
+
},
|
418
|
+
{
|
419
|
+
'http' => {
|
420
|
+
'port'=> '80'
|
421
|
+
}
|
422
|
+
}
|
423
|
+
]
|
424
|
+
include_recipe 'ufw'
|
425
|
+
|
426
|
+
# swapfile
|
427
|
+
swap_file '/mnt/swap' do
|
428
|
+
size node[:app_name][:base][:swap_size]
|
429
|
+
end
|
430
|
+
|
431
|
+
# htop
|
432
|
+
package 'htop'
|
433
|
+
CODE
|
434
|
+
end
|
435
|
+
|
436
|
+
gsub_file 'recipes/base.rb', 'app_name', app_name
|
437
|
+
|
438
|
+
git add: '.'
|
439
|
+
git commit: "-m 'Add the base recipe'"
|
440
|
+
|
441
|
+
# ----- Create database recipe ------------------------------------------------------------------------
|
442
|
+
|
443
|
+
puts
|
444
|
+
say_status 'recipes', 'Creating database recipe...', :yellow
|
445
|
+
puts '-'*80, ''; sleep 0.25
|
446
|
+
|
447
|
+
file 'recipes/database.rb' do <<-CODE
|
448
|
+
# This is where you will store a copy of your key on the chef-client
|
449
|
+
secret = Chef::EncryptedDataBagItem.load_secret('/etc/chef/encrypted_data_bag_secret')
|
450
|
+
|
451
|
+
# This decrypts the data bag contents of "#{app_name}_secrets/production.json" and uses the key defined at variable "secret"
|
452
|
+
encrypted_data_bag = Chef::EncryptedDataBagItem.load('#{app_name}_secrets', 'production', secret)
|
453
|
+
|
454
|
+
include_recipe '#{app_name}::base'
|
455
|
+
include_recipe 'postgresql'
|
456
|
+
include_recipe 'postgresql::client'
|
457
|
+
include_recipe 'postgresql::server'
|
458
|
+
include_recipe 'postgresql::libpq'
|
459
|
+
|
460
|
+
pg_user 'postgres' do
|
461
|
+
privileges superuser: true, createdb: true, login: true
|
462
|
+
password encrypted_data_bag['database_password']
|
463
|
+
end
|
464
|
+
CODE
|
465
|
+
end
|
466
|
+
|
467
|
+
git add: '.'
|
468
|
+
git commit: "-m 'Add the database recipe'"
|
469
|
+
|
470
|
+
# ----- Create cache recipe ---------------------------------------------------------------------------
|
471
|
+
|
472
|
+
puts
|
473
|
+
say_status 'recipes', 'Creating cache recipe...', :yellow
|
474
|
+
puts '-'*80, ''; sleep 0.25
|
475
|
+
|
476
|
+
file 'recipes/cache.rb' do <<-CODE
|
477
|
+
include_recipe '#{app_name}::base'
|
478
|
+
|
479
|
+
node.override[:redisio][:mirror] = 'http://download.redis.io/releases'
|
480
|
+
node.override[:redisio][:version] = '2.8.3'
|
481
|
+
include_recipe 'redisio::install'
|
482
|
+
include_recipe 'redisio::enable'
|
483
|
+
CODE
|
484
|
+
end
|
485
|
+
|
486
|
+
git add: '.'
|
487
|
+
git commit: "-m 'Add the cache recipe'"
|
488
|
+
|
489
|
+
# ----- Create web recipe -----------------------------------------------------------------------------
|
490
|
+
|
491
|
+
puts
|
492
|
+
say_status 'recipes', 'Creating web recipe...', :yellow
|
493
|
+
puts '-'*80, ''; sleep 0.25
|
494
|
+
|
495
|
+
file 'recipes/web.rb' do <<-'CODE'
|
496
|
+
secret = Chef::EncryptedDataBagItem.load_secret('/etc/chef/encrypted_data_bag_secret')
|
497
|
+
encrypted_data_bag = Chef::EncryptedDataBagItem.load('app_name_secrets', 'production', secret)
|
498
|
+
|
499
|
+
include_recipe 'app_name::base'
|
500
|
+
|
501
|
+
# environment variables
|
502
|
+
|
503
|
+
template '/etc/profile' do
|
504
|
+
source 'profile.erb'
|
505
|
+
variables({
|
506
|
+
:cookbook_name => cookbook_name,
|
507
|
+
:database_password => encrypted_data_bag['database_password'],
|
508
|
+
:cache_password => encrypted_data_bag['cache_password'],
|
509
|
+
:mail_password => encrypted_data_bag['mail_password'],
|
510
|
+
:token_rails_secret => encrypted_data_bag['token_rails_secret'],
|
511
|
+
:token_devise_secret => encrypted_data_bag['token_devise_secret'],
|
512
|
+
:token_devise_pepper => encrypted_data_bag['token_devise_pepper']
|
513
|
+
})
|
514
|
+
end
|
515
|
+
|
516
|
+
# git
|
517
|
+
|
518
|
+
apt_repository 'git' do
|
519
|
+
uri 'http://ppa.launchpad.net/git-core/ppa/ubuntu'
|
520
|
+
distribution node[:lsb][:codename]
|
521
|
+
components %w[main]
|
522
|
+
keyserver 'keyserver.ubuntu.com'
|
523
|
+
key 'E1DF1F24'
|
524
|
+
action :add
|
525
|
+
end
|
526
|
+
|
527
|
+
include_recipe 'git'
|
528
|
+
|
529
|
+
repo_path = "/home/#{node[:app_name][:base][:username]}/#{cookbook_name}.git"
|
530
|
+
|
531
|
+
directory repo_path do
|
532
|
+
owner node[:app_name][:base][:username]
|
533
|
+
group node[:app_name][:base][:username]
|
534
|
+
mode 0755
|
535
|
+
end
|
536
|
+
|
537
|
+
execute 'initialize new bare git repo' do
|
538
|
+
user node[:app_name][:base][:username]
|
539
|
+
group node[:app_name][:base][:username]
|
540
|
+
command "cd #{repo_path} && git init --bare"
|
541
|
+
only_if { !File.exists? "#{repo_path}/HEAD" }
|
542
|
+
end
|
543
|
+
|
544
|
+
# node
|
545
|
+
|
546
|
+
node.override[:nodejs][:install_method] = 'binary'
|
547
|
+
node.override[:nodejs][:version] = '0.10.24'
|
548
|
+
node.override[:nodejs][:checksum] = 'fb6487e72d953451d55e28319c446151c1812ed21919168b82ab1664088ecf46'
|
549
|
+
node.override[:nodejs][:checksum_linux_x64] = '423018f6a60b18d0dddf3007c325e0cc8cf55099'
|
550
|
+
node.override[:nodejs][:checksum_linux_x86] = 'fb6487e72d953451d55e28319c446151c1812ed21919168b82ab1664088ecf46'
|
551
|
+
include_recipe 'nodejs::install_from_binary'
|
552
|
+
|
553
|
+
# ruby
|
554
|
+
|
555
|
+
node.override[:rvm][:default_ruby] = node[:app_name][:web][:ruby_version]
|
556
|
+
node.override[:rvm][:global_gems] = [ { 'name' => 'bundler', 'version' => '1.5.1' } ]
|
557
|
+
node.override[:rvm][:group_users] = [ node[:app_name][:base][:username] ]
|
558
|
+
|
559
|
+
include_recipe 'rvm::system'
|
560
|
+
|
561
|
+
# nginx
|
562
|
+
|
563
|
+
apt_repository 'nginx' do
|
564
|
+
uri 'http://ppa.launchpad.net/nginx/stable/ubuntu'
|
565
|
+
distribution node[:lsb][:codename]
|
566
|
+
components %w[main]
|
567
|
+
keyserver 'keyserver.ubuntu.com'
|
568
|
+
key 'C300EE8C'
|
569
|
+
action :add
|
570
|
+
end
|
571
|
+
|
572
|
+
node.override[:nginx][:gzip_comp_level] = '4'
|
573
|
+
|
574
|
+
include_recipe 'nginx'
|
575
|
+
|
576
|
+
cookbook_file 'nginx_virtualhost.conf' do
|
577
|
+
path "#{node[:nginx][:dir]}/sites-available/#{cookbook_name}.conf"
|
578
|
+
group node[:nginx][:user]
|
579
|
+
owner node[:nginx][:user]
|
580
|
+
mode '0644'
|
581
|
+
end
|
582
|
+
|
583
|
+
nginx_site "#{cookbook_name}.conf"
|
584
|
+
|
585
|
+
include_recipe 'logrotate'
|
586
|
+
|
587
|
+
logrotate_app 'nginx' do
|
588
|
+
cookbook 'logrotate'
|
589
|
+
path ["#{node[:nginx][:log_dir]}/access.log", "#{node[:nginx][:log_dir]}/error.log"]
|
590
|
+
options ['missingok', 'notifempty']
|
591
|
+
frequency 'daily'
|
592
|
+
create '0644 root adm'
|
593
|
+
rotate 365
|
594
|
+
end
|
595
|
+
CODE
|
596
|
+
end
|
597
|
+
|
598
|
+
gsub_file 'recipes/web.rb', 'app_name', app_name
|
599
|
+
|
600
|
+
git add: '.'
|
601
|
+
git commit: "-m 'Add the web recipe'"
|
602
|
+
|
603
|
+
# ----- Create default recipe -------------------------------------------------------------------------
|
604
|
+
|
605
|
+
puts
|
606
|
+
say_status 'recipes', 'Creating default recipe...', :yellow
|
607
|
+
puts '-'*80, ''; sleep 0.25
|
608
|
+
|
609
|
+
run 'rm -f recipes/default.rb'
|
610
|
+
file 'recipes/default.rb' do <<-CODE
|
611
|
+
include_recipe '#{app_name}::database'
|
612
|
+
include_recipe '#{app_name}::cache'
|
613
|
+
include_recipe '#{app_name}::web'
|
614
|
+
CODE
|
615
|
+
end
|
616
|
+
|
617
|
+
git add: '.'
|
618
|
+
git commit: "-m 'Add the default recipe'"
|
619
|
+
|
620
|
+
# ----- Installation complete message -----------------------------------------------------------------
|
621
|
+
|
622
|
+
puts
|
623
|
+
say_status 'success', "\e[1m\Everything has been setup successfully\e[0m", :cyan
|
624
|
+
puts
|
625
|
+
say_status 'question', 'Are you new to chef and berkshelf?', :yellow
|
626
|
+
say_status 'answer', 'Check the orats wiki for the walk through', :white
|
627
|
+
puts
|
628
|
+
say_status 'question', 'Are you somewhat experienced with chef?', :yellow
|
629
|
+
say_status 'answer', 'Setup your encrypted data bag and bootstrap the node', :white
|
630
|
+
puts '-'*80
|
data/lib/orats/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Janetakis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -72,8 +72,9 @@ files:
|
|
72
72
|
- lib/orats/cli.rb
|
73
73
|
- lib/orats/server.rb
|
74
74
|
- lib/orats/shell.rb
|
75
|
-
- lib/orats/templates/
|
76
|
-
- lib/orats/templates/
|
75
|
+
- lib/orats/templates/auth.rb
|
76
|
+
- lib/orats/templates/base.rb
|
77
|
+
- lib/orats/templates/cook.rb
|
77
78
|
- lib/orats/templates/includes/Gemfile
|
78
79
|
- lib/orats/version.rb
|
79
80
|
- orats.gemspec
|