├── data_bags ├── .gitkeep └── users │ └── deploy.json ├── nodes ├── .gitkeep └── phoenix_server.json ├── roles ├── .gitkeep ├── postgres-server.json ├── phoenix-app.json └── server.json ├── environments ├── .gitkeep └── production.json ├── site-cookbooks ├── .gitkeep └── phoenix-git │ ├── metadata.rb │ ├── CHANGELOG.md │ ├── attributes │ └── default.rb │ ├── templates │ └── default │ │ └── post-receive.erb │ ├── README.md │ └── recipes │ └── default.rb ├── .gitignore ├── phoenix_server.json ├── Gemfile ├── .chef └── knife.rb ├── Vagrantfile ├── Berksfile ├── LICENSE ├── README.md ├── Berksfile.lock └── Gemfile.lock /data_bags/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nodes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /roles/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /environments/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site-cookbooks/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /cookbooks/ 2 | .vagrant/ 3 | chef-ubuntu-trusty64.box 4 | -------------------------------------------------------------------------------- /phoenix_server.json: -------------------------------------------------------------------------------- 1 | { 2 | "run_list": [ 3 | 4 | ], 5 | "automatic": { 6 | "ipaddress": "128.199.111.164" 7 | } 8 | } -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "knife-solo", "~> 0.4.2" 4 | gem "chef", "~> 12.4.1" 5 | gem "berkshelf", "~> 3.3.0" 6 | -------------------------------------------------------------------------------- /environments/production.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "production", 3 | "default_attributes": { 4 | }, 5 | "json_class":"Chef::Environment", 6 | "chef_type":"environment" 7 | } 8 | -------------------------------------------------------------------------------- /.chef/knife.rb: -------------------------------------------------------------------------------- 1 | cookbook_path ["cookbooks", "site-cookbooks"] 2 | node_path "nodes" 3 | role_path "roles" 4 | environment_path "environments" 5 | data_bag_path "data_bags" 6 | #encrypted_data_bag_secret "data_bag_key" 7 | 8 | knife[:berkshelf_path] = "cookbooks" 9 | -------------------------------------------------------------------------------- /roles/postgres-server.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postgres-server", 3 | "description": "Postgres database server", 4 | "default_attributes": { 5 | 6 | }, 7 | "json_class": "Chef::Role", 8 | "run_list": [ 9 | "postgresql::server", 10 | "monit_configs-tlq::postgres" 11 | ], 12 | "chef_type": "role" 13 | } 14 | -------------------------------------------------------------------------------- /site-cookbooks/phoenix-git/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'phoenix-git' 2 | maintainer 'Gabriel Jaldon' 3 | maintainer_email 'gjaldon85@gmail.com' 4 | license 'MIT' 5 | description 'Installs/Configures phoenix-git' 6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) 7 | version '0.1.0' 8 | depends 'database' 9 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure(2) do |config| 5 | config.vm.box = "chef-ubuntu-trusty64" 6 | config.vm.provision "file", source: "~/.ssh/id_rsa.pub", destination: "~/.ssh/me.pub" 7 | config.vm.provision "shell", inline: "cat ~vagrant/.ssh/me.pub >> ~vagrant/.ssh/authorized_keys" 8 | config.vm.network :forwarded_port, guest: 80, host: 4567 9 | 10 | config.ssh.forward_agent = true 11 | 12 | config.vm.provider "virtualbox" do |v| 13 | v.memory = 1024 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /site-cookbooks/phoenix-git/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | phoenix-git CHANGELOG 2 | ===================== 3 | 4 | This file is used to list changes made in each version of the phoenix-git cookbook. 5 | 6 | 0.1.0 7 | ----- 8 | - [your_name] - Initial release of phoenix-git 9 | 10 | - - - 11 | Check the [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) for help with Markdown. 12 | 13 | The [Github Flavored Markdown page](http://github.github.com/github-flavored-markdown/) describes the differences between markdown on github and standard markdown. 14 | -------------------------------------------------------------------------------- /roles/phoenix-app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phoenix-app", 3 | "description": "Runs Phoenix apps", 4 | "default_attributes": { 5 | "elixir": { 6 | "version": "1.0.5" 7 | }, 8 | "firewall" : { 9 | "rules" : [ 10 | {"allow http on port 80" : {"port" : 80}}, 11 | {"allow http on port 8080" : {"port" : 8080}}, 12 | {"allow http on port 8081" : {"port" : 8081}} 13 | ] 14 | } 15 | }, 16 | "json_class": "Chef::Role", 17 | "run_list": [ 18 | "recipe[elixir::default]", 19 | "recipe[phoenix-git::default]", 20 | "recipe[ufw::default]" 21 | ], 22 | "chef_type": "role" 23 | } 24 | -------------------------------------------------------------------------------- /site-cookbooks/phoenix-git/attributes/default.rb: -------------------------------------------------------------------------------- 1 | default['phoenix-git']['app_name'] = "app" 2 | default['phoenix-git']['app_port_1'] = "8080" 3 | default['phoenix-git']['app_port_2'] = "8081" 4 | default['phoenix-git']['mix_env'] = "prod" 5 | 6 | # Postgres DB attributes 7 | default['phoenix-git']['db_name'] = "postgres_prod" 8 | default['phoenix-git']['db_connection'] = { 9 | :host => "127.0.0.1", 10 | :port => 5432, 11 | :username => "postgres", 12 | :password => "test" 13 | } 14 | 15 | default['phoenix-git']['node_build_commands'] = [ 16 | "node_modules/bower/bin/bower install", 17 | "node_modules/brunch/bin/brunch build --production" 18 | ] 19 | -------------------------------------------------------------------------------- /data_bags/users/deploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "deploy", 3 | // generate this with: openssl passwd -1 "plaintextpassword" 4 | "password": "$1$h8MtHlGj$rbJKmlMV3fccIxmCMs/Px0", 5 | // the below should contain a list of ssh public keys which should 6 | // be able to login as deploy 7 | "ssh_keys": [ 8 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5ib00zUqWzzec3QnITg8q/6Ua9LG5uBkAmtLhzxxAcTNqCTreBj4FWnBIxFnyYoldEkeqEsvfCzvNsRhDh85vN3Q5GbaByIpvG2ZE02p9T+RlAuA9TMZ+Ih/HEKD/ts6cIsmlTCjdUmZawJH6xYnWa5nDGVtmnFG9TnwD2QBVimtdg1N8Cg5Y5eNlNOTQlYxchKkKTbxAlC6k21/pVpPyHms4meJdaHjfKRchme90jW/8dlHo//hH4bGqR7o44P/Eu/KMypvGPPLN99NdIrsUZGfQKyjWEI+hWelCoaPIeMTZg3J0NkQI0mtRTebVp5U8Zo4U7bDOhskZmOp8gAjV gjaldon85@gmail.com" 9 | ], 10 | "groups": ["sysadmin"], 11 | "shell": "\/bin\/bash" 12 | } 13 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | source "https://supermarket.chef.io" 2 | 3 | cookbook 'apt', github: 'opscode-cookbooks/apt' 4 | cookbook 'chef-solo-search', github: 'edelight/chef-solo-search' 5 | cookbook 'database', github: 'opscode-cookbooks/database' 6 | cookbook 'elixir', github: 'reset/elixir-cookbook' 7 | cookbook 'fail2ban', github: 'opscode-cookbooks/fail2ban' 8 | cookbook 'locales', github: 'phbergsmann/chef-locales' 9 | cookbook 'look_and_feel-tlq', github: 'TalkingQuickly/look_and_feel-tlq' 10 | cookbook 'monit-tlq', github: 'TalkingQuickly/monit-tlq', branch: 'master' 11 | cookbook 'monit_configs-tlq', github: 'TalkingQuickly/monit_configs-tlq', branch: 'master' 12 | cookbook 'ntp', github: 'gmiranda23/ntp' 13 | cookbook 'openssh', github: 'opscode-cookbooks/openssh' 14 | cookbook 'postgresql', github: 'opscode-cookbooks/postgresql' 15 | cookbook 'sudo', github: 'opscode-cookbooks/sudo' 16 | cookbook 'ufw', github: 'opscode-cookbooks/ufw' 17 | cookbook 'users', github: 'opscode-cookbooks/users' 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Gabriel Jaldon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phoenix Server Template 2 | 3 | ### Introduction 4 | 5 | This is a Chef template for provisioning a Phoenix server that accepts `git push` deploys 6 | on Ubuntu Trusty. It includes Postgresql as database and Node for compiling static assets. 7 | 8 | This has only been tested in Vagrant and DigitalOcean. It is likely going to work in other 9 | cloud providers, but haven't tried out myself. 10 | 11 | ### Usage 12 | 13 | This template was designed with the use of `chef-solo` in mind so we will be using `knife-solo` 14 | commands. 15 | 16 | 1. We need to prepare the VPS for provisioning by installing Chef and its dependencies by doing: 17 | 18 | ```elixir 19 | knife solo prepare root@yourserverip 20 | ``` 21 | 22 | 2. Provision your server! 23 | 24 | ```elixir 25 | knife solo cook root@yourserverip nodes/phoenix_server.json 26 | ``` 27 | 28 | You can customize the attributes to adapt this template according to your needs. Keep in mind to 29 | secure your secrets in your attributes by using `chef-vault` or encrypted attributes. 30 | 31 | 32 | ### Important Links 33 | 34 | - [Chef docs](https://docs.chef.io/resources.html) 35 | - [License](https://github.com/gjaldon/phoenix_server_template/blob/master/LICENSE) 36 | 37 | 38 | 39 | PS - Contributions and Feedback are always welcome! 40 | -------------------------------------------------------------------------------- /nodes/phoenix_server.json: -------------------------------------------------------------------------------- 1 | { 2 | "environment":"production", 3 | "authorization": { 4 | "sudo": { 5 | // the deploy user specifically gets sudo rights 6 | // if you're using vagrant it's worth adding "vagrant" 7 | // to this array 8 | // The password for the deploy user is set in data_bags/users/deploy.json 9 | // and should be generated using: 10 | // openssl passwd -1 "plaintextpassword" 11 | "users": ["deploy", "vagrant"] 12 | } 13 | }, 14 | "postgresql" : { 15 | "password" : { 16 | // this should be generated with: 17 | // openssl passwd -1 "plaintextpassword" 18 | // currently test 19 | "postgres" : "test" 20 | } 21 | }, 22 | "monit": { 23 | "notify_emails" : ["email@example.com"], 24 | "enable_emails" : false, 25 | "web_interface" : { 26 | // the plaintext monit username and password 27 | "allow" : ["your_username","your_password"] 28 | }, 29 | "mailserver" : { 30 | // the easiest option is to use something like 31 | // Mailgun or Sengrid 32 | "host" : "mailserver.example.com", 33 | "port" : "999", 34 | "username" : "your_username", 35 | "password" : "your_password", 36 | "hostname" : "the_hostname" 37 | } 38 | }, 39 | "build_essential": { 40 | "compiletime": true 41 | }, 42 | "run_list": [ 43 | "role[server]", 44 | "role[postgres-server]", 45 | "role[phoenix-app]" 46 | ], 47 | "automatic": { 48 | "ipaddress": "127.0.0.1" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /site-cookbooks/phoenix-git/templates/default/post-receive.erb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | app_name=<%= node["phoenix-git"]['app_name'] %> 4 | app_port_1=<%= node["phoenix-git"]['app_port_1'] %> 5 | app_port_2=<%= node["phoenix-git"]['app_port_2'] %> 6 | 7 | for f in /etc/profile.d/*; do source $f; done 8 | 9 | git --work-tree=/var/www/$app_name.com --git-dir=/var/repo/$app_name.git checkout -f 10 | 11 | mix local.hex --force 12 | mix local.rebar --force 13 | 14 | cd /var/www/$app_name.com 15 | 16 | <%= (["npm install"] + node["phoenix-git"]["node_build_commands"]).join(" && ") %> 17 | 18 | if [ $PORT = $app_port_1 ]; then 19 | PORT=8888 mix do deps.get, deps.compile, phoenix.digest, ecto.migrate && 20 | PORT=$app_port_2 elixir --detached -S mix phoenix.server && 21 | sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port $app_port_2 22 | sleep 5 && sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port $app_port_1 23 | previous_port=$(sudo lsof -t -i:$app_port_1) 24 | if [ -n $previous_port ]; then 25 | sudo kill $previous_port 26 | fi 27 | echo "export PORT=$app_port_2" > /etc/profile.d/PORT.sh 28 | else 29 | PORT=8888 mix do deps.get, deps.compile, phoenix.digest, ecto.migrate && 30 | PORT=$app_port_1 elixir --detached -S mix phoenix.server && 31 | sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port $app_port_1 32 | sleep 5 && sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port $app_port_2 33 | previous_port=$(sudo lsof -t -i:$app_port_2) 34 | if [ -n $previous_port ]; then 35 | sudo kill $previous_port 36 | fi 37 | echo "export PORT=$app_port_1" > /etc/profile.d/PORT.sh 38 | fi 39 | -------------------------------------------------------------------------------- /site-cookbooks/phoenix-git/README.md: -------------------------------------------------------------------------------- 1 | phoenix-git Cookbook 2 | ==================== 3 | TODO: Enter the cookbook description here. 4 | 5 | e.g. 6 | This cookbook makes your favorite breakfast sandwich. 7 | 8 | Requirements 9 | ------------ 10 | TODO: List your cookbook requirements. Be sure to include any requirements this cookbook has on platforms, libraries, other cookbooks, packages, operating systems, etc. 11 | 12 | e.g. 13 | #### packages 14 | - `toaster` - phoenix-git needs toaster to brown your bagel. 15 | 16 | Attributes 17 | ---------- 18 | TODO: List your cookbook attributes here. 19 | 20 | e.g. 21 | #### phoenix-git::default 22 |
| Key | 25 |Type | 26 |Description | 27 |Default | 28 |
|---|---|---|---|
| ['phoenix-git']['bacon'] | 31 |Boolean | 32 |whether to include bacon | 33 |true | 34 |