├── .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 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /images/ansible.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 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 | --------------------------------------------------------------------------------