├── .gitignore
├── ansible.cfg
├── images
├── redis.png
├── ansible.png
├── redis.svg
└── ansible.svg
├── hosts
├── templates
├── redis.service.j2
└── rc.local
├── Vagrantfile
├── README.md
└── playbook.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | .vagrant
2 | *.retry
--------------------------------------------------------------------------------
/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | inventory = $PWD/hosts
3 |
--------------------------------------------------------------------------------
/images/redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeblum/redis-playbook/HEAD/images/redis.png
--------------------------------------------------------------------------------
/hosts:
--------------------------------------------------------------------------------
1 | [webservers]
2 | 127.0.0.1
3 | [localhost]
4 | localhost ansible_connection=local
--------------------------------------------------------------------------------
/images/ansible.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeblum/redis-playbook/HEAD/images/ansible.png
--------------------------------------------------------------------------------
/templates/redis.service.j2:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Redis In-Memory Data Store
3 | After=network.target
4 |
5 | [Service]
6 | User={{ redis_user }}
7 | Group={{ redis_group }}
8 | ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
9 | ExecStop=/usr/local/bin/redis-cli shutdown
10 | Restart=always
11 |
12 | [Install]
13 | WantedBy=multi-user.target
--------------------------------------------------------------------------------
/templates/rc.local:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 | #
3 | # rc.local
4 | #
5 | # This script is executed at the end of each multiuser runlevel.
6 | # Make sure that the script will "exit 0" on success or any other
7 | # value on error.
8 | #
9 | # In order to enable or disable this script just change the execution
10 | # bits.
11 | #
12 | # By default this script does nothing.
13 |
14 | exit 0
15 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | Vagrant.configure("2") do |config|
5 | config.vm.box = "bento/ubuntu-16.04"
6 |
7 | config.vm.provider "virtualbox" do |vb|
8 | # Customize the amount of memory on the VM:
9 | vb.memory = "1024"
10 | end
11 |
12 | # Disable the new default behavior introduced in Vagrant 1.7, to
13 | # ensure that all Vagrant machines will use the same SSH key pair.
14 | # See https://github.com/mitchellh/vagrant/issues/5005
15 | config.ssh.insert_key = false
16 |
17 | # expose redis to the host machine
18 | config.vm.network "forwarded_port", guest: 6379, host: 6379, protocol: "tcp"
19 |
20 | config.vm.provision "ansible" do |ansible|
21 | ansible.verbose = "v"
22 | ansible.playbook = "playbook.yml"
23 | # enable access from the host machine - DEVELOPMENT ONLY
24 | # on a web server this would expose redis to the world
25 | ansible.extra_vars = {
26 | redis_bind_addr: "0.0.0.0",
27 | redis_socket_permissions: 777
28 | }
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## redis-playbook
2 |
3 |
4 | ---
5 |
6 |
7 | an Ansible playbook for deploying a secured and optimized Redis instance
8 |
9 | Based originally on DigitailOcean's guide to deploying a Redis instance:
10 |
11 | [How to install and configure redis on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-redis-on-ubuntu-16-04)
12 |
13 | This playbook looks to automate the tedious setup process by performing the following tasks:
14 |
15 | - Update OS with apt-get
16 | - Install Redis dependencies
17 | - Install Redis from source (test, make)
18 | - Configure and secure Redis-as-a-service
19 | - Create a `redis` user and group
20 | - Create data and logging directories
21 | - Enable Redis socket support (`redis-cli -a redis -s /var/run/redis/redis.sock`)
22 |
23 | - Optimize Redis
24 | - Disable Transparent Huge Pages (THP) support
25 | - Increase TCP backlog
26 | - Enable low-memory DB saves
27 |
28 | Run `vagrant up` to provision a Redis instance available from your local machine.
29 |
--------------------------------------------------------------------------------
/images/redis.svg:
--------------------------------------------------------------------------------
1 |
2 |
17 |
--------------------------------------------------------------------------------
/images/ansible.svg:
--------------------------------------------------------------------------------
1 |
2 |
19 |
--------------------------------------------------------------------------------
/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # based on Digital Ocean's installation guide
3 | # https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-redis-on-ubuntu-16-04
4 | - hosts: all
5 | sudo: True
6 | remote_user: root
7 |
8 | vars:
9 | ipv4_addr: '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
10 | redis_user: redis
11 | redis_group: redis
12 | # change for production
13 | redis_bind_addr: 127.0.0.1
14 | redis_port: 6379
15 | redis_tcp_sockets: 511
16 | redis_socket: /var/run/redis/redis.sock
17 | redis_socket_permissions: 770
18 | redis_logfile: /var/log/redis/redis-server.log
19 | # generate a 32-character password with apg:
20 | # apg -m 32 -x 1 -a 1 -n 1
21 | redis_password: redis
22 |
23 | # install python 2.7 on Ubuntu > 14.x
24 | # solves "/bin/sh: 1: /usr/bin/python: not found" issue with
25 | # later Ubuntu releases
26 | gather_facts: no
27 | pre_tasks:
28 | - name: 'install python2'
29 | raw: sudo apt-get -y install python-simplejson
30 |
31 | tasks:
32 | - name: update apt cache
33 | apt: update_cache=yes
34 |
35 | - name: install required packages
36 | apt: name={{ item }} state=present
37 | with_items:
38 | - build-essential
39 | - tcl
40 |
41 | - name: download redis src
42 | # remote_src broken in ~ 2.1
43 | # https://github.com/ansible/ansible-modules-core/issues/4752
44 | unarchive:
45 | src: http://download.redis.io/redis-stable.tar.gz
46 | copy: no
47 | dest: /tmp
48 | mode: u=rwx,g=rx,o=rx
49 | owner: root
50 | creates: /tmp/redis-stable
51 |
52 | - name: make redis
53 | make: chdir=/tmp/redis-stable
54 |
55 | - name: test and install redis
56 | make: chdir=/tmp/redis-stable target={{ item }}
57 | become: yes
58 | with_items:
59 | - test
60 | - install
61 |
62 | - name: create /etc/redis, data, logs, and socket directories
63 | file: path={{ item }} state=directory
64 | with_items:
65 | - /etc/redis
66 | - /var/lib/redis
67 | - /var/log/redis
68 | - /var/run/redis
69 |
70 | - name: copy default redis.conf
71 | # create a copy of the default redis.conf
72 | copy: remote_src=True
73 | src=/tmp/redis-stable/redis.conf
74 | dest=/etc/redis/redis.conf
75 | become: yes
76 |
77 | - name: configure systemmd
78 | lineinfile: dest=/etc/redis/redis.conf
79 | regexp='^supervised no$'
80 | line='supervised systemd'
81 | state=present
82 |
83 | - name: store redis data in /var/lib/redis
84 | lineinfile: dest=/etc/redis/redis.conf
85 | regexp='^dir ./$'
86 | line='dir /var/lib/redis'
87 | state=present
88 |
89 | - name: secure redis
90 | lineinfile:
91 | dest: /etc/redis/redis.conf
92 | regexp: '^# requirepass \w*$'
93 | line: 'requirepass {{ redis_password }}'
94 | state: present
95 |
96 | - name: bind to redis.bind_addr
97 | lineinfile:
98 | dest: /etc/redis/redis.conf
99 | regexp: '^bind {{ ipv4_addr }}$'
100 | line: 'bind {{ redis_bind_addr }}'
101 | state: present
102 |
103 | - name: configure logging
104 | lineinfile:
105 | dest: /etc/redis/redis.conf
106 | regexp: '^logfile ""$'
107 | line: 'logfile {{ redis_logfile }}'
108 | state: present
109 |
110 | - name: Check rc.local exists
111 | stat:
112 | path: /etc/rc.local
113 | register: rc_local
114 |
115 | - name: Create rc.local if not present
116 | when: rc_local.islnk is not defined
117 | template:
118 | src: templates/rc.local
119 | dest: /etc/rc.local
120 | mode: '0755'
121 |
122 | - name: disable Transparent Huge Pages (THP) support
123 | lineinfile: dest=/etc/rc.local
124 | insertbefore='^exit 0$'
125 | line='echo never > /sys/kernel/mm/transparent_hugepage/enabled'
126 | state=present
127 | become: yes
128 |
129 | - name: fix TCP backlog
130 | lineinfile: dest=/etc/rc.local
131 | insertbefore='^exit 0$'
132 | line='net.core.somaxconn={{ redis_tcp_sockets }}'
133 | state=present
134 | become: yes
135 |
136 | - command: sysctl -w net.core.somaxconn={{ redis_tcp_sockets }}
137 | become: yes
138 |
139 | - name: enable low-memory background saves
140 | lineinfile: dest=/etc/sysctl.conf
141 | regexp=''
142 | insertafter=EOF
143 | line='vm.overcommit_memory = 1'
144 | become: yes
145 |
146 | - command: sysctl vm.overcommit_memory=1
147 | become: yes
148 |
149 | - name: create redis-as-a-service
150 | template: src=templates/redis.service.j2
151 | dest=/etc/systemd/system/redis.service
152 | owner=root
153 | group=root
154 | mode=0644
155 |
156 | - name: create redis group
157 | group: name=redis state=present
158 |
159 | - name: create redis user
160 | user: name={{ redis_user }}
161 | group={{ redis_group }}
162 | shell=/bin/bash
163 | createhome=no
164 |
165 | - name: enable unix socket support
166 | lineinfile: dest=/etc/redis/redis.conf
167 | regexp='^unixsocket {{ redis_socket }}$'
168 | line='unixsocket {{ redis_socket }}'
169 | state=present
170 | insertafter=EOF
171 | create=True
172 |
173 | - name: configure unix socket permissions
174 | lineinfile: dest=/etc/redis/redis.conf
175 | regexp='^unixsocketperm {{ redis_socket_permissions }}$'
176 | line='unixsocketperm {{ redis_socket_permissions }}'
177 | state=present
178 | insertafter=EOF
179 | create=True
180 |
181 | - name: set permissions for redis
182 | file: path={{ item }} state=touch owner=redis group=redis mode=0770
183 | with_items:
184 | - /etc/redis
185 | - /var/lib/redis
186 | - /var/log/redis
187 | - /var/run/redis
188 | become: yes
189 |
190 | - name: start redis
191 | service: name=redis state=restarted enabled=yes
192 |
--------------------------------------------------------------------------------