Initial Ansible NAS commit

This commit is contained in:
David Stephens 2017-08-28 16:31:54 +01:00
commit 83fee520d8
23 changed files with 554 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
group_vars/all.yml
group_vars/vpn_credentials.yml

6
.gitmodules vendored Normal file
View file

@ -0,0 +1,6 @@
[submodule "roles/samba"]
path = roles/samba
url = https://github.com/bertvv/ansible-role-samba.git
[submodule "roles/docker"]
path = roles/docker
url = https://github.com/geerlingguy/ansible-role-docker.git

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 David Stephens
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

53
README.md Normal file
View file

@ -0,0 +1,53 @@
### Ansible NAS
After getting burned by broken FreeNAS updates one too many times, I figured I could do a much better job myself using
just a stock Ubuntu install, some clever Ansible config and a bunch of docker containers.
## What This Provides
* Any number of Samba shares for you to store your stuff
* Via Docker:
- [Duplicati](https://www.duplicati.com/) for backing up your stuff
- [Transmission](https://transmissionbt.com/) BitTorrent client (with OpenVPN if you have a supported VPN provider)
- [Sonarr](https://sonarr.tv/) for downloading and managing TV episodes
- [CouchPotato](https://couchpota.to/) for downloading and managing movies
- [Portainer](https://portainer.io/) for managing Docker and running custom images
- [Glances](https://nicolargo.github.io/glances/) for seeing the state of your system via a web browser
## What This Doesn't Do
Ansible NAS doesn't set up your disk partitions, primarily because getting it wrong can be incredibly destructive.
That aside, configuring partitions is usually a one-time (or very infrequent) event, so there's not much to be
gained by automating it.
## Hardware
Ansible NAS should work on any recent Ubuntu box. Development was done on Ubuntu 16.04.3 LTS.
## How To Use
1. `git clone https://www.github.com/davestephens/ansible-nas && cd ansible-nas`
2. Copy `group_vars/all.yml.dist` to `group_vars/all.yml`.
3. Open up `group_vars/all.yml` and follow the instructions there for configuring your Ansible NAS.
3. If you plan to use Transmission with OpenVPN, also copy `group_vars/vpn_credentials.yml.dist` to
`group_vars/vpn_credentials.yml` and input your settings.
4. Modify `inventory` and update it with the hostname of your NAS box.
5. Run the playbook - something like `ansible-playbook -i inventory nas.yml` should do you nicely.
## Migrating from FreeNAS
Assuming that your Ubuntu system disk is separate from your storage (it should be!):
1. Disconnect your drives.
2. Run Ansible NAS against your server.
3. Reconnect your drives.
4. SSH to the server and run `zpool import` to determine available ZFS pools.
5. `zpool import <pool_name>` against the pools you want to attach.
6. `chown -R root:root /mnt/<volume>` to fix the ownership of the data
## TODO
1. Handle Docker containers being enabled then subsequently disabled (i.e clean up afterwards)
2. SMART disk monitoring
## Contributing
Contributions welcome!

2
ansible.cfg Normal file
View file

@ -0,0 +1,2 @@
[defaults]
retry_files_enabled = False

152
group_vars/all.yml.dist Normal file
View file

@ -0,0 +1,152 @@
###
### Ansible NAS Features
###
# Set these options to true or false to toggle specific features
# BitTorrent
# If you plan to use Transmission with OpenVPN, you'll need to copy group_vars/vpn_credentials.yml.dist
# to group_vars/vpn_credentials.yml, then update it with your own settings.
transmission_with_openvpn_enabled: true
transmission_enabled: false
# Media Sourcing
sonarr_enabled: true
couchpotato_enabled: false
# System Management
portainer_enabled: true
glances_enabled: true
# Backup & Restore
crashplan_enabled: true
duplicati_enabled: true
###
### General
###
# Sets the hostname of your Ansible NAS
ansible_nas_hostname: bender
# Update all apt packages when playbook is run
keep_packages_updated: false
# Will be added to the docker group to give user command line access to docker
ansible_nas_user: david
# Where you want Docker to store its images and container data.
docker_home: /mnt/Volume2/docker
# Your time zone, passed to Docker containers at startup
time_zone: Europe/London
###
### Samba
###
# The location where all shares will be created by default. Can be overridden on a per-share basis.
# This path will be mounted to backup containers, ie Crashplan, Duplicati
samba_shares_root: /mnt/Volume3
# The account used when Samba shares are accessed. Shouldn't need to change this unless you want to
# mess with Samba user permissions.
samba_guest_account: nobody
# Shares you want published over Samba.
samba_shares:
- name: downloads
comment: 'Stuff downloaded'
guest_ok: yes
public: yes
writable: yes
path: "{{ samba_shares_root }}/downloads"
- name: movies
comment: 'Movies'
guest_ok: yes
public: yes
writable: yes
path: "{{ samba_shares_root }}/movies"
- name: tv
comment: 'TV Episodes'
guest_ok: yes
public: yes
writable: yes
path: "{{ samba_shares_root }}/tv"
- name: dump
comment: 'File dump'
guest_ok: yes
public: yes
writable: yes
path: "{{ samba_shares_root }}/dump"
- name: games
comment: 'Games'
guest_ok: yes
public: yes
writable: yes
path: "{{ samba_shares_root }}/games"
- name: photos
comment: 'Pictures'
guest_ok: yes
public: yes
writable: yes
path: "{{ samba_shares_root }}/photos"
##################################################################
###### You shouldn't need to edit anything below this point ######
##################################################################
###
### Transmission
###
transmission_config_directory: "{{ docker_home }}/transmission/config"
transmission_download_directory: "{{ samba_shares_root }}/downloads"
transmission_watch_directory: "{{ samba_shares_root }}/torrents"
transmission_user_id: 0
transmission_group_id: 0
transmission_local_network: "192.168.1.0/24"
###
### Duplicati
###
duplicati_data_directory: "{{ docker_home }}/duplicati/config"
###
### Sonarr
###
sonarr_data_directory: "{{ docker_home }}/sonarr/config"
sonarr_tv_directory: "{{ samba_shares_root }}/TV"
sonarr_user_id: 0
sonarr_group_id: 0
###
### OpenVPN
###
openvpn_config_directory: "{{ docker_home }}/openvpn"
###
### Portainer
###
portainer_data_directory: "{{ docker_home }}/portainer/config"
###
### Crashplan
###
crashplan_user_id: 0
crashplan_group_id: 0
###
### Couchpotato
###
couchpotato_user_id: 0
couchpotato_group_id: 0

View file

@ -0,0 +1,9 @@
###
### VPN Credentials
###
# If you're using Transmission with a VPN, you'll need to set these credentials.
# See https://hub.docker.com/r/haugene/transmission-openvpn/ for supported VPN providers.
openvpn_username: super_secret_username
openvpn_password: super_secret_password
openvpn_provider: NORDVPN
openvpn_config: uk64.nordvpn.com.udp1194

3
inventory Normal file
View file

@ -0,0 +1,3 @@
[all]
192.168.1.30

6
nas.yml Normal file
View file

@ -0,0 +1,6 @@
---
- hosts: all
roles:
- samba
- docker
- ansible-nas

View file

@ -0,0 +1,26 @@
---
- name: Create Couchpotato Directories
file:
path: "{{ item }}"
state: directory
# mode: 0755
with_items:
- "{{ docker_home }}/couchpotato/config"
- name: Couchpotato Docker Container
docker_container:
name: couchpotato
image: linuxserver/couchpotato
pull: true
volumes:
- "{{ docker_home }}/couchpotato/config:/config:rw"
- "{{ samba_shares_root }}/BitTorrent/completed:/downloads:rw"
- "{{ samba_shares_root }}/Movies/Movies:/movies:rw"
- "/etc/timezone:/etc/timezone:ro"
ports:
- "5050:5050"
env:
PUID: "{{ couchpotato_user_id }}"
PGID: "{{ couchpotato_group_id }}"
restart_policy: unless-stopped
memory: 1g

View file

@ -0,0 +1,26 @@
---
- name: Create Crashplan Directories
file:
path: "{{ item }}"
state: directory
# mode: 0755
with_items:
- "{{ docker_home }}/crashplan/config"
- name: Crashplan Docker Container
docker_container:
name: crashplan
image: jlesage/crashplan
pull: true
volumes:
- "{{ docker_home }}/crashplan/config:/config:rw"
- "{{ samba_shares_root }}:/storage:ro"
- "/etc/timezone:/etc/timezone:ro"
ports:
- "5800:5800"
- "5900:5900"
env:
USER_ID: "{{ crashplan_user_id }}"
GROUP_ID: "{{ crashplan_group_id }}"
restart_policy: unless-stopped
memory: 2g

View file

@ -0,0 +1,34 @@
---
- name: install pip
apt:
name: python-pip
state: present
- name: 'Install docker-py'
pip:
name: docker-py
state: present
- name: create docker home
file:
path: "{{ docker_home }}"
mode: 0755
state: directory
- name: add user account to docker group
user:
name: "{{ ansible_nas_user }}"
group: docker
append: yes
- name: update docker home from install default
template:
src: daemon.json
dest: /etc/docker/daemon.json
register: docker_config
- name: restart docker
service:
name: docker
state: restarted
when: docker_config.changed

View file

@ -0,0 +1,21 @@
---
- name: Create Duplicati Directory
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ duplicati_data_directory }}"
- name: Dupicati Docker Container
docker_container:
name: duplicati
image: linuxserver/duplicati
pull: true
ports:
- "8200:8200"
volumes:
- "{{ duplicati_data_directory }}:/config:rw"
- "{{ samba_shares_root }}:/source:ro"
- "/etc/timezone:/etc/timezone:ro"
restart_policy: unless-stopped
memory: 4g

View file

@ -0,0 +1,28 @@
---
- name: Update apt-cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Upgrade all packages
apt:
name: "*"
state: latest
when: keep_packages_updated == true
- name: Install some packages
apt:
name: "{{ item }}"
state: present
with_items:
- smartmontools
- htop
- zfs
- bonnie++
- unzip
# - name: Configure smartmontools
- name: "Set hostname to {{ ansible_nas_hostname }}"
hostname:
name: "{{ ansible_nas_hostname }}"

View file

@ -0,0 +1,16 @@
- name: Glances Docker Container
docker_container:
name: glances
image: nicolargo/glances
pull: true
ports:
- "61208:61208"
- "61209:61209"
volumes:
#- "/glances.conf:/glances/conf/glances.conf"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "/etc/timezone:/etc/timezone:ro"
env:
GLANCES_OPT: "-w"
restart_policy: unless-stopped
memory: 1g

View file

@ -0,0 +1,19 @@
---
- include: general.yml
- include: docker.yml
- include: portainer.yml
when: portainer_enabled == true
- include: transmission.yml
when: transmission_enabled == true
- include: transmission_with_openvpn.yml
when: transmission_with_openvpn_enabled == true
- include: sonarr.yml
when: sonarr_enabled == true
- include: glances.yml
when: glances_enabled == true
- include: duplicati.yml
when: duplicati_enabled == true
- include: crashplan.yml
when: crashplan_enabled == true
- include: couchpotato.yml
when: couchpotato_enabled == true

View file

@ -0,0 +1,22 @@
---
- name: Create Portainer Directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ portainer_data_directory }}"
- name: Portainer Docker Container
docker_container:
name: portainer
image: portainer/portainer
pull: true
volumes:
- "{{ portainer_data_directory }}:/data:rw"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "/etc/timezone:/etc/timezone:ro"
ports:
- "9000:9000"
restart_policy: unless-stopped
memory: 1g

View file

@ -0,0 +1,26 @@
---
- name: Create Sonarr Directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ sonarr_data_directory }}"
- name: Sonarr
docker_container:
name: sonarr
image: linuxserver/sonarr
pull: true
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "{{ sonarr_tv_directory }}:/tv:rw"
- "{{ transmission_download_directory }}/complete:/downloads:rw"
- "{{ sonarr_data_directory }}:/config:rw"
- "/etc/timezone:/etc/timezone:ro"
ports:
- "8989:8989"
env:
PUID: "{{ sonarr_user_id }}"
PGID: "{{ sonarr_group_id }}"
restart_policy: unless-stopped
memory: 1g

View file

@ -0,0 +1,30 @@
---
- name: Create Transmission Directories
file:
path: "{{ item }}"
state: directory
# mode: 0755
with_items:
- "{{ transmission_config_directory }}"
- "{{ transmission_download_directory }}"
- "{{ transmission_watch_directory }}"
- name: Transmission Docker Container
docker_container:
name: transmission
image: linuxserver/transmission
pull: true
volumes:
- "{{ transmission_config_directory }}:/config:rw"
- "{{ transmission_download_directory }}:/downloads:rw"
- "{{ transmission_watch_directory }}:/watch:rw"
- "/etc/timezone:/etc/timezone:ro"
ports:
- "9092:9091"
- "51414:51413"
env:
PUID: "{{ transmission_user_id }}"
PGID: "{{ transmission_group_id }}"
restart_policy: unless-stopped
memory: 1g

View file

@ -0,0 +1,46 @@
---
- include_vars: group_vars/vpn_credentials.yml
- name: Create Transmission Directories
file:
path: "{{ item }}"
state: directory
# mode: 0755
with_items:
- "{{ transmission_config_directory }}"
- "{{ transmission_download_directory }}"
- "{{ transmission_watch_directory }}"
- name: Transmission with VPN
docker_container:
name: transmission-openvpn
image: haugene/transmission-openvpn
pull: true
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "{{ transmission_download_directory }}:/storage/downloads:rw"
- "{{ transmission_config_directory }}:/config:rw"
- "{{ transmission_watch_directory }}:/storage/watch:rw"
- "/etc/timezone:/etc/timezone:ro"
ports:
- "9091:9091"
- "51413:51413"
env:
TRANSMISSION_HOME: /config
TRANSMISSION_DOWNLOAD_DIR: /storage/downloads/complete
TRANSMISSION_INCOMPLETE_DIR: /storage/downloads/incomplete
TRANSMISSION_WATCH_DIR: /storage/watch
OPENVPN_PROVIDER: "{{ openvpn_provider }}"
OPENVPN_USERNAME: "{{ openvpn_username }}"
OPENVPN_PASSWORD: "{{ openvpn_password }}"
OPENVPN_CONFIG: "{{ openvpn_config }}"
PUID: "{{ transmission_user_id }}"
PGID: "{{ transmission_group_id }}"
LOCAL_NETWORK: "{{ transmission_local_network }}"
ENABLE_UFW: false
devices:
- /dev/net/tun
capabilities:
- NET_ADMIN
restart_policy: unless-stopped
memory: 1g

View file

@ -0,0 +1,4 @@
{
"graph": "{{ docker_home }}/data",
"storage-driver": "overlay"
}

1
roles/docker Submodule

@ -0,0 +1 @@
Subproject commit 0960f85f784fbaaee9d2e3a606db7899542ae2fb

1
roles/samba Submodule

@ -0,0 +1 @@
Subproject commit b63ca1385ee8e186b6b4060778b780512c6a37d7