├── src ├── settings │ ├── .config │ ├── config.json │ └── demo │ │ └── config.json ├── config.js ├── package.json ├── server.js └── jokeService.js ├── deploy ├── demo ├── deploy.yml ├── roles │ ├── nginx │ │ ├── vars │ │ │ └── main.yml │ │ ├── tasks │ │ │ └── main.yml │ │ └── templates │ │ │ └── nginx.conf.j2 │ ├── common │ │ └── tasks │ │ │ └── main.yml │ └── nodejs │ │ └── tasks │ │ └── main.yml ├── ansible.cfg ├── vars │ └── default.yml ├── templates │ └── nginx.j2 ├── deploy-nginx.yml └── deploy-app.yml ├── .gitignore └── README.md /src/settings/.config: -------------------------------------------------------------------------------- 1 | demo -------------------------------------------------------------------------------- /src/settings/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "development", 3 | "port": 8080 4 | } -------------------------------------------------------------------------------- /src/settings/demo/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "demo", 3 | "port": 9000 4 | } -------------------------------------------------------------------------------- /deploy/demo: -------------------------------------------------------------------------------- 1 | demo ansible_ssh_host=104.236.198.187 2 | 3 | [app-servers] 4 | demo -------------------------------------------------------------------------------- /deploy/deploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: deploy-app.yml 3 | - include: deploy-nginx.yml -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bak 2 | *.log 3 | .vagrant/ 4 | node_modules/ 5 | *.zip 6 | .idea 7 | .sass-cache 8 | Thumbs.db -------------------------------------------------------------------------------- /deploy/roles/nginx/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nginx_user: www-data 3 | nginx_pid: /var/run/nginx.pid 4 | nginx_worker_processes: 2 5 | nginx_worker_connections: 1024 6 | -------------------------------------------------------------------------------- /deploy/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | roles_path = /etc/ansible/roles 3 | transport = ssh 4 | host_key_checking = False 5 | 6 | [ssh_connection] 7 | ssh_args = -o ForwardAgent=yes 8 | 9 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var setty = require('setty'); 3 | setty.load({settingsDir: path.join(__dirname, './settings')}); 4 | 5 | module.exports = { 6 | env: setty.get("env"), 7 | port: setty.get("port") 8 | }; 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sample node.js app deployment with Ansible 2 | === 3 | 4 | Install ansible: [Ansible](http://docs.ansible.com/intro_installation.html) 5 | 6 | 7 | Deploying app 8 | -- 9 | ``` 10 | cd deploy 11 | ansible-playbook deploy.yml -i demo -u root -e env=demo 12 | ``` 13 | -------------------------------------------------------------------------------- /deploy/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: update apt packages 3 | sudo: yes 4 | apt: update_cache=yes cache_valid_time=3600 5 | 6 | - name: install basic apt packages 7 | sudo: yes 8 | apt: pkg={{ item }} state=present 9 | with_items: 10 | - curl 11 | - git -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jokeGenerator", 3 | "version": "0.0.0", 4 | "main": "server.js", 5 | "dependencies": { 6 | "request": "^2.46.0", 7 | "setty": "^1.0.2" 8 | }, 9 | "devDependencies": {}, 10 | "engines": { 11 | "node": ">=0.10.0" 12 | }, 13 | "scripts": { 14 | "start": "node server.js" 15 | }, 16 | "private": true 17 | } 18 | -------------------------------------------------------------------------------- /deploy/vars/default.yml: -------------------------------------------------------------------------------- 1 | --- 2 | #Configuration for scheduler 3 | ######################################################### 4 | 5 | repo_url: git@github.com:paralect/ansible-node-sample.git 6 | repo_version: master 7 | app_name: demo 8 | server_name: jokes.paralect.com 9 | nginx_servers: ["localhost:9000"] 10 | deploy_dir: "~/{{ app_name }}" 11 | deploy_app_dir: "~/{{ app_name }}/{{ app_name }}-app" 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/server.js: -------------------------------------------------------------------------------- 1 | var jokeService = require('./jokeService'); 2 | var config = require('./config'); 3 | 4 | var app = require('http').createServer(function(req, res){ 5 | jokeService.getRandomJoke(function(err, joke){ 6 | res.writeHead(200); 7 | res.end(joke); 8 | }); 9 | }); 10 | 11 | app.listen(config.port, function(){ 12 | console.log([new Date(), 'Demo server started on ', config.port].join("")); 13 | }); 14 | -------------------------------------------------------------------------------- /deploy/templates/nginx.j2: -------------------------------------------------------------------------------- 1 | upstream main_nodes { 2 | {% for server in nginx_servers %} 3 | server {{ server }}; 4 | {% endfor %} 5 | } 6 | 7 | server { 8 | listen 80; 9 | server_name {{server_name}}; 10 | 11 | location / { 12 | proxy_set_header Upgrade $http_upgrade; 13 | proxy_set_header Connection "upgrade"; 14 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 15 | proxy_set_header Host $host; 16 | proxy_http_version 1.1; 17 | proxy_pass http://main_nodes; 18 | } 19 | } -------------------------------------------------------------------------------- /deploy/roles/nodejs/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: update apt packages 3 | sudo: yes 4 | apt: update_cache=yes cache_valid_time=3600 5 | 6 | - name: install nodejs requirements 7 | sudo: yes 8 | apt: pkg={{ item }} state=present 9 | with_items: 10 | - python-software-properties 11 | - python 12 | - g++ 13 | - make 14 | 15 | - name: add Chris Lea's nodejs ppa 16 | sudo: yes 17 | apt_repository: repo='ppa:chris-lea/node.js' 18 | 19 | - name: install nodejs 20 | sudo: yes 21 | apt: pkg=nodejs update_cache=yes 22 | -------------------------------------------------------------------------------- /src/jokeService.js: -------------------------------------------------------------------------------- 1 | var request = require('request'); 2 | 3 | module.exports.getRandomJoke = function(callback){ 4 | var r = request.defaults({followRedirect: true, 5 | followAllRedirects: false, 6 | json: true, 7 | headers: { 8 | Accept:'*/*', 9 | 'Cache-Control':'no-cache' 10 | }}); 11 | 12 | r.get('http://api.icndb.com/jokes/random', function(err, httpResponse, body){ 13 | if(err){ 14 | console.log('Failed to fetch joke', err); 15 | return callback(null); 16 | } 17 | 18 | callback(null, body.value.joke); 19 | }); 20 | }; -------------------------------------------------------------------------------- /deploy/deploy-nginx.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Deploy nginx 3 | hosts: app-servers 4 | vars_files: 5 | - ["vars/default.yml"] 6 | roles: 7 | - nginx 8 | tasks: 9 | - name: copy nginx virtual host file 10 | sudo: yes 11 | template: src="{{ inventory_dir }}/templates/nginx.j2" 12 | dest="/etc/nginx/sites-available/{{app_name}}" 13 | owner=root 14 | group=root 15 | 16 | - name: link nginx virtual host file 17 | sudo: yes 18 | file: src="/etc/nginx/sites-available/{{app_name}}" 19 | dest="/etc/nginx/sites-enabled/{{app_name}}" 20 | state=link 21 | 22 | - name: restart nginx 23 | sudo: yes 24 | service: name=nginx state=restarted -------------------------------------------------------------------------------- /deploy/roles/nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: add nginx ppa 3 | sudo: yes 4 | apt_repository: repo='ppa:nginx/stable' 5 | 6 | - name: update apt-get 7 | sudo: yes 8 | apt: update_cache=yes cache_valid_time=3600 9 | 10 | - name: install nginx 11 | sudo: yes 12 | apt: pkg=nginx state=present 13 | 14 | - name: copy nginx.conf 15 | sudo: yes 16 | template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root 17 | tags: 18 | - nginx 19 | 20 | - name: setup nginx host file dirs 21 | sudo: yes 22 | file: name=/etc/nginx/{{ item }} state=directory owner=root group=root 23 | with_items: 24 | - sites-available 25 | - sites-enabled 26 | 27 | - name: ensure default nginx has been deleted 28 | sudo: yes 29 | file: dest=/etc/nginx/sites-enabled/default state=absent 30 | 31 | - name: restart nginx 32 | sudo: yes 33 | service: name=nginx state=restarted enabled=yes 34 | tags: 35 | - nginx -------------------------------------------------------------------------------- /deploy/roles/nginx/templates/nginx.conf.j2: -------------------------------------------------------------------------------- 1 | user {{ nginx_user }}; 2 | worker_processes {{ nginx_worker_processes }}; 3 | pid {{ nginx_pid }}; 4 | 5 | events { 6 | worker_connections {{ nginx_worker_connections }}; 7 | } 8 | 9 | http { 10 | 11 | sendfile on; 12 | tcp_nopush on; 13 | tcp_nodelay on; 14 | keepalive_timeout 65; 15 | types_hash_max_size 2048; 16 | # server_tokens off; 17 | 18 | include /etc/nginx/mime.types; 19 | default_type application/octet-stream; 20 | 21 | access_log /var/log/nginx/access.log; 22 | error_log /var/log/nginx/error.log; 23 | server_names_hash_bucket_size 128; 24 | 25 | ### Gzip Settings 26 | gzip on; 27 | gzip_disable "msie6"; 28 | # gzip_vary on; 29 | # gzip_proxied any; 30 | # gzip_comp_level 6; 31 | # gzip_buffers 16 8k; 32 | # gzip_http_version 1.1; 33 | # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 34 | 35 | ### Virtual Host Configs 36 | include /etc/nginx/conf.d/*.conf; 37 | include /etc/nginx/sites-enabled/*; 38 | } 39 | -------------------------------------------------------------------------------- /deploy/deploy-app.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Deploy application 3 | hosts: app-servers 4 | vars_files: 5 | - ["vars/default.yml"] 6 | roles: 7 | - common 8 | - nodejs 9 | tasks: 10 | - name: Install global npm packages 11 | npm: name={{ item }} global=yes 12 | sudo: yes 13 | with_items: 14 | - forever 15 | 16 | - name: Make app dir 17 | sudo: no 18 | shell: mkdir -p {{ deploy_app_dir }} 19 | changed_when: False 20 | 21 | - name: Pull sources from the repository. 22 | sudo: no 23 | git: repo={{ repo_url }} 24 | ssh_opts="-o StrictHostKeyChecking=no" 25 | dest={{ deploy_app_dir }} 26 | version={{ repo_version }} 27 | 28 | - name: install npm packages for root 29 | sudo: no 30 | shell: chdir={{ deploy_app_dir }}/src npm install 31 | 32 | - name: create config file 33 | sudo: yes 34 | lineinfile: dest={{ deploy_app_dir }}/src/settings/.config create=yes state=present line="{{ env }}" 35 | 36 | - name: Forever list 37 | shell: forever list 38 | register: forever_processes 39 | 40 | - name: Restart forever if it started already 41 | shell: > 42 | forever stop {{ deploy_app_dir }}/src/server.js 43 | when: forever_processes.stdout.find('/src/server.js') != -1 44 | 45 | - name: Start node with forever 46 | shell: > 47 | forever start 48 | --append 49 | -e {{ deploy_dir }}/{{ app_name }}-error.log 50 | -l {{ deploy_dir }}/{{ app_name }}-forever.log 51 | -o {{ deploy_dir }}/{{ app_name }}-node.log 52 | {{ deploy_app_dir}}/src/server.js 53 | sudo: yes --------------------------------------------------------------------------------