From 004593e833b5811857e2e8e0f28c12f0c802e18b Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Tue, 1 Aug 2023 21:21:32 +0200 Subject: [PATCH 01/12] 80 Update README.md --- README.md | 5 +++-- services/homer/assets/config.yml | 18 +++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 9ea0e39..bfb37d0 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,10 @@ ![GitHub forks](https://img.shields.io/github/forks/veerendra2/raspberrypi-homeserver?style=plastic) ![GitHub issues](https://img.shields.io/github/issues/veerendra2/raspberrypi-homeserver?style=plastic) ![GitHub release (release name instead of tag name)](https://img.shields.io/github/v/release/veerendra2/raspberrypi-homeserver?include_prereleases&style=plastic) -# Raspberry Pi Home Server +# Self-host Docker Swarm Stacks +> _Previuosly known as "Raspberry Pi homeserver"_

-A collection of applications and tools to make awesome Raspberry Pi homerserver +A collection of applications and tools

diff --git a/services/homer/assets/config.yml b/services/homer/assets/config.yml index a731b40..79d8d1a 100644 --- a/services/homer/assets/config.yml +++ b/services/homer/assets/config.yml @@ -152,15 +152,15 @@ services: url: "/nextcloud/" method: "get" - - name: Password Manager - icon: "" - items: - - name: "Vaultwarden" - type: "Ping" - logo: "assets/tools/vaultwarden.png" - subtitle: "Rust implementation of Bitwarden API" - url: "/vaultwarden/" - method: "get" + # - name: Password Manager + # icon: "" + # items: + # - name: "Vaultwarden" + # type: "Ping" + # logo: "assets/tools/vaultwarden.png" + # subtitle: "Rust implementation of Bitwarden API" + # url: "/vaultwarden/" + # method: "get" # - name: Search # icon: "" From 1eacded01b24eeb7259d0ffd83f1afc52599610b Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Mon, 28 Aug 2023 23:14:15 +0200 Subject: [PATCH 02/12] Add prepare_dev_setup role and fix lints --- .ansible-lint | 2 + .github/workflows/lint.yml | 30 +++++++++ .yamllint | 7 ++ README.md | 2 - inventory.yml | 16 ++--- main.yml | 35 ++++------ requirements.yml | 3 + tasks/bettercap.yml | 33 ---------- tasks/deploy-services.yml | 10 +-- tasks/docker.yml | 38 ----------- tasks/pigpio.yml | 41 ++++++------ tasks/pihole.yml | 56 ++++++++-------- tasks/prepare-pi.yml | 128 ++++++++++--------------------------- tasks/smoke-tests.yml | 88 ++++++++++++------------- tasks/ufw.yml | 72 ++++++++++----------- vars.yml | 77 ++-------------------- 16 files changed, 228 insertions(+), 410 deletions(-) create mode 100644 .ansible-lint create mode 100644 .github/workflows/lint.yml create mode 100644 .yamllint create mode 100644 requirements.yml delete mode 100644 tasks/bettercap.yml delete mode 100644 tasks/docker.yml diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..37ca0f9 --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,2 @@ +--- +verbosity: 1 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..cd3592a --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,30 @@ +--- +name: Lint +'on': + pull_request: + push: + branches: + - main + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@v2 + + - name: Set up Python3 + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Install yamllint + run: pip3 install yamllint + + - name: Run yamllint + run: | + yamllint . + + - name: Run ansible-lint + uses: ansible/ansible-lint@main diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..6d56f1b --- /dev/null +++ b/.yamllint @@ -0,0 +1,7 @@ +--- +extends: default + +rules: + line-length: + max: 200 + level: warning diff --git a/README.md b/README.md index 86b33ff..6521ff0 100644 --- a/README.md +++ b/README.md @@ -193,8 +193,6 @@ ![Architecture](https://user-images.githubusercontent.com/8393701/235324714-75620112-a89b-4d10-ab9d-2e44de75d36b.jpg) ## Getting Started -> :warning: **CAUTION** Ansible playbooks are highly unstable, needs to rework in future [#54](https://github.com/veerendra2/raspberrypi-homeserver/issues/54). -> > Refer [Gitbook Docs](https://dust6765.gitbook.io/raspberrypi-home-server/) for more details and how to deploy manually * Follow prerequisite [manual steps](https://dust6765.gitbook.io/raspberrypi-home-server/settings/manual-steps) to prepare Pi diff --git a/inventory.yml b/inventory.yml index be2c756..8bbf3da 100644 --- a/inventory.yml +++ b/inventory.yml @@ -1,11 +1,11 @@ all: - hosts: - atom: - ansible_ssh_port: 22 - ansible_ssh_host: 192.168.0.120 - ansible_ssh_user: veerendra - #ansible_ssh_password: - extra_hosts: - - "atom:192.168.0.130" # Wifi Address + # hosts: + # atom: + # ansible_ssh_port: 22 + # ansible_ssh_host: 192.168.0.120 + # ansible_ssh_user: veerendra + # # ansible_ssh_password: + # extra_hosts: + # - "atom:192.168.0.130" # Wifi Address localhost: ansible_connection: local \ No newline at end of file diff --git a/main.yml b/main.yml index 0c98f0f..44a5e1e 100644 --- a/main.yml +++ b/main.yml @@ -1,38 +1,27 @@ -# Author: Veerendra K -# Description: An Ansible playbook to make awesome Raspberry Pi homeserver - -- name: Raspberry Pi Homeserver - hosts: localhost - gather_facts: yes +--- +- name: Homeserver Automation + hosts: all vars_files: - vars.yml - pre_tasks: - - name: Run update - apt: - upgrade: true - update_cache: yes - ignore_errors: yes - become: yes - - post_tasks: - - name: Run autoremove - apt: - autoremove: yes - become: yes + roles: + - veerendra2.prepare_dev_setup tasks: - name: Prepare Pi - import_tasks: tasks/prepare-pi.yml + ansible.builtin.import_tasks: tasks/prepare-pi.yml + become: true tags: prepare-pi - name: Deploy services - import_tasks: tasks/deploy-services.yml + ansible.builtin.import_tasks: tasks/deploy-services.yml + become: true tags: services - name: Setup firewall rules - import_tasks: tasks/ufw.yml + ansible.builtin.import_tasks: tasks/ufw.yml + become: true - name: Performing smoke tests - import_tasks: tasks/smoke-tests.yml + ansible.builtin.import_tasks: tasks/smoke-tests.yml tags: never diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000..9fd4476 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,3 @@ +--- +roles: + - name: veerendra2.prepare_dev_setup diff --git a/tasks/bettercap.yml b/tasks/bettercap.yml deleted file mode 100644 index 9ddbde0..0000000 --- a/tasks/bettercap.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- -- name: Create temporary bettercap build directory - tempfile: - state: directory - suffix: build - register: tempdir - -- name: Build bettercap - shell: | - go env -w GO111MODULE=off - go get -u github.com/bettercap/bettercap - environment: - GOPATH: "{{ tempdir.path }}" - -- name: Install bettercap - shell: | - mv {{ tempdir.path }}/bin/bettercap /usr/local/bin/ - rm -rf {{ tempdir.path }} - bettercap -version - become: yes - register: output - -- name: Display bettercap version - debug: - msg: "{{ output.stdout }}" - when: output.rc == 0 - -# https://www.bettercap.org/usage/webui/ -- name: Install bettercap caplets - shell: bettercap -eval "caplets.update; ui.update; q" - when: output.rc == 0 - ignore_errors: true - become: true diff --git a/tasks/deploy-services.yml b/tasks/deploy-services.yml index 7fbc7ca..fdf2fc3 100644 --- a/tasks/deploy-services.yml +++ b/tasks/deploy-services.yml @@ -3,7 +3,7 @@ # https://github.com/veerendra2/raspberrypi-homeserver/issues/54 - name: Create base directory - file: + ansible.builtin.file: path: "{{ services_base_dir_location }}" state: directory owner: "{{ run_user }}" @@ -14,14 +14,14 @@ when: "'pihole' in services" - name: Create .vpn_ip file for torrent service - copy: + ansible.builtin.copy: dest: services/torrent/.vpn_ip content: | VPN_IP={{ vpn_ip }} when: "vpn_ip and 'torrent' in services" - name: Synchronize services directories - synchronize: + ansible.posix.synchronize: src: "services/" dest: "{{ services_base_dir_location }}" delete: false @@ -29,7 +29,7 @@ perms: false - name: Create networks - docker_stack: + community.docker.docker_stack: state: present name: traefik compose: @@ -37,7 +37,7 @@ when: "'traefik' in services" - name: Deploy service stacks - docker_stack: + community.docker.docker_stack: state: present name: "{{ item }}" compose: diff --git a/tasks/docker.yml b/tasks/docker.yml deleted file mode 100644 index 25b7acf..0000000 --- a/tasks/docker.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -- name: Download scripts - get_url: - url: "https://get.docker.com/" - dest: "/tmp/get-docker.sh" - mode: "0776" - -- block: - - name: Install docker - command: "/tmp/get-docker.sh" - environment: - CHANNEL: stable - - - name: Start docker daemon - service: - name: docker - state: started - enabled: true - - - name: Add user in docker group - user: - name: "{{ run_user }}" - groups: docker - append: true - - - name: Create /etc/docker/daemon.json - template: - src: templates/docker_daemon.json.j2 - dest: /etc/docker/daemon.json - - - name: Enable docker swarm mode - docker_swarm: - state: present - advertise_addr: "{{ docker_swarm_advertise_addr }}" - register: output - when: enable_docker_swarm_mode|bool == true - - become: yes \ No newline at end of file diff --git a/tasks/pigpio.yml b/tasks/pigpio.yml index 428e939..70e63f9 100644 --- a/tasks/pigpio.yml +++ b/tasks/pigpio.yml @@ -1,27 +1,29 @@ --- - name: Create temporary to pigpio build - tempfile: + ansible.builtin.tempfile: state: directory suffix: build register: tempdir - name: Download pigpio - get_url: + ansible.builtin.get_url: url: https://github.com/joan2937/pigpio/archive/master.zip dest: "{{ tempdir.path }}" +# TODO need to test! +- name: Extract pigpio + ansible.builtin.unarchive: + src: "{{ tempdir.path }}/master.zip" + dest: "{{ tempdir.path }}" -- name: Run make and make install pigpio - shell: | - unzip pigpio-master.zip - cd pigpio-master - sudo make - sudo make install - args: +- name: Build and install pigpio + community.general.make: chdir: "{{ tempdir.path }}" - become: yes + target: install + params: + NUM_THREADS: 2 - name: Set systemd unit parameters for pigpiod - set_fact: + ansible.builtin.set_fact: name: pigpiod description: Daemon required to control GPIO pins via pigpio exec_start_cmd: /usr/local/bin/pigpiod @@ -32,28 +34,25 @@ service_type: forking - name: Create pigpiod systemd unit - template: + ansible.builtin.template: src: templates/systemd_unit.service.j2 dest: /lib/systemd/system/pigpiod.service - become: yes - name: Enable and start pigpiod systemd daemon - systemd: + ansible.builtin.systemd: name: pigpiod enabled: yes daemon_reload: yes state: started - become: yes - name: Copy fan.py script - copy: + ansible.builtin.copy: src: scripts/fan.py dest: /usr/local/bin/fan.py mode: '0744' - become: yes - name: Set systemd unit parameters for fan-py - set_fact: + ansible.builtin.set_fact: name: fan-py description: Daemon required to control fan speed via pigpio exec_start_cmd: /usr/bin/python3 /usr/local/bin/fan.py @@ -64,15 +63,13 @@ service_type: simple - name: Create fan-py systemd unit - template: + ansible.builtin.template: src: templates/systemd_unit.service.j2 dest: /lib/systemd/system/fan-py.service - become: yes - name: Enable and start fan-py systemd daemon - systemd: + ansible.builtin.systemd: name: fan-py enabled: yes daemon_reload: yes state: started - become: yes diff --git a/tasks/pihole.yml b/tasks/pihole.yml index ac3351e..37bf925 100644 --- a/tasks/pihole.yml +++ b/tasks/pihole.yml @@ -1,35 +1,33 @@ --- # https://github.com/pi-hole/docker-pi-hole#installing-on-ubuntu-or-fedora -- name: Configure systemd-resolved for PiHole - block: - - name: Disable stub resolver in systemd-resolved config - ini_file: - path: /etc/systemd/resolved.conf - section: Resolve - option: DNSStubListener - value: "no" - backup: true - - name: Create backup /etc/resolv.conf - copy: - remote_src: yes - src: /etc/resolv.conf - dest: /etc/resolv.conf.backup +- name: Disable stub resolver in systemd-resolved config + ini_file: + path: /etc/systemd/resolved.conf + section: Resolve + option: DNSStubListener + value: "no" + backup: true - - name: Remove /etc/resolv.conf - file: - path: /etc/resolv.conf - state: absent +- name: Create backup /etc/resolv.conf + copy: + remote_src: yes + src: /etc/resolv.conf + dest: /etc/resolv.conf.backup - - name: Create link /etc/resolv.conf - file: - src: /run/systemd/resolve/resolv.conf - dest: /etc/resolv.conf - state: link - ignore_errors: yes +- name: Remove /etc/resolv.conf + file: + path: /etc/resolv.conf + state: absent - - name: Restart systemd-resolved - service: - name: systemd-resolved - state: restarted - become: yes +- name: Create link /etc/resolv.conf + file: + src: /run/systemd/resolve/resolv.conf + dest: /etc/resolv.conf + state: link + ignore_errors: yes + +- name: Restart systemd-resolved + service: + name: systemd-resolved + state: restarted diff --git a/tasks/prepare-pi.yml b/tasks/prepare-pi.yml index 466815e..f3d72d8 100644 --- a/tasks/prepare-pi.yml +++ b/tasks/prepare-pi.yml @@ -1,112 +1,48 @@ --- -- name: Install necessary packages - apt: - name: "{{ pkgs }}" - state: latest - update_cache: yes - install_recommends: no - force_apt_get: yes - become: true - -- name: Install snap packages - snap: - name: "{{ snaps }}" - classic: yes - become: true - -- name: Install pypi packages - pip: - name: "{{ pypi }}" - state: present - executable: "pip3" - -- name: Download scripts - get_url: - url: "{{ item.value }}" - dest: "/tmp/{{ item.key }}.sh" - mode: "0776" - loop: "{{ lookup('dict', scripts, wantlist=True) }}" - -- name: Run scripts - command: "/tmp/{{ item.key }}.sh" - loop: "{{ lookup('dict', scripts, wantlist=True) }}" - -- name: Set authorized keys taken from url - authorized_key: - user: "{{ run_user }}" - state: present - key: "{{ github_username_keys }}" - -- name: Generate ssh key pair - openssh_keypair: - path: "{{ [ansible_env.HOME, '.ssh', 'id_rsa'] | path_join }}" - force: no - -- name: Check fan-py daemon is loaded - systemd: - name: fan-py - register: output - -- name: Install pigpio and Pi fan controller - include_tasks: pigpio.yml - when: output.status.LoadState != 'loaded' - -- block: - - name: Check docker installed - shell: docker --version - register: output - - debug: - msg: "{{ output.stdout }}" - rescue: - - name: Install and configure docker - include_tasks: docker.yml - -- block: - - name: Check bettercap installed - shell: bettercap --version - register: output - - debug: - msg: "{{ output.stdout }}" - rescue: - - name: Install bettercap - include_tasks: bettercap.yml - -# POWER OPTIMIZATION -- block: - - name: Stop and disable hciuart and bluetooth deamon - systemd: - name: "{{ item }}" - state: stopped - enabled: no - with_items: - - bluetooth - - hciuart - - name: Disable HDMI Output - shell: /usr/bin/tvservice -o - when: disable_bluetooth|bool == true - become: yes - -- name: Reboot Pi after upgrade - reboot: - post_reboot_delay: 10 - when: reboot_after_pi_preparation|bool == true and ansible_connection != 'local' - become: yes +- name: Install fan script + block: + - name: Check fan-py daemon is loaded + ansible.builtin.systemd: + name: fan-py + register: output + + - name: Install pigpio and Pi fan controller + ansible.builtin.include_tasks: pigpio.yml + when: output.status.LoadState != 'loaded' + when: install_fan_script + +- name: Power optimization + block: + - name: Stop and disable hciuart and bluetooth deamon + ansible.builtin.systemd: + name: "{{ item }}" + state: stopped + enabled: no + with_items: + - bluetooth + - hciuart + - name: Disable HDMI Output + ansible.builtin.command: /usr/bin/tvservice -o + when: disable_bluetooth|bool == true - name: Configure disk mounts in /etc/fstab - mount: + ansible.posix.mount: path: "{{ item.value }}" src: "{{ item.key }}" fstype: ext4 opts: rw,async state: mounted loop: "{{ lookup('dict', disk_mount_dirs) }}" - become: yes - name: Change mount directories ownership - file: + ansible.builtin.file: path: "{{ item.value }}" owner: "{{ run_user }}" group: "{{ run_user }}" mode: "0744" loop: "{{ lookup('dict', disk_mount_dirs) }}" - become: yes + +- name: Reboot Pi after upgrade + ansible.builtin.reboot: + post_reboot_delay: 10 + when: reboot_after_pi_preparation and ansible_connection != 'local' diff --git a/tasks/smoke-tests.yml b/tasks/smoke-tests.yml index 17c66d5..1fda3d1 100644 --- a/tasks/smoke-tests.yml +++ b/tasks/smoke-tests.yml @@ -1,49 +1,49 @@ --- - - name: Fetch docker swarm info - docker_swarm_info: - nodes: yes - services: yes - ignore_errors: yes - register: swarm_info +- name: Fetch docker swarm info + community.docker.docker_swarm_info: + nodes: yes + services: yes + ignore_errors: yes + register: swarm_info - - debug: - msg: | - ***************** DOCKER SWARM INFO ***************** - can_talk_to_docker: {{ swarm_info.can_talk_to_docker }} - docker_swarm_active: {{ swarm_info.docker_swarm_active }} - docker_swarm_manager: {{ swarm_info.docker_swarm_manager }} - failed: {{ swarm_info.failed }} - ***************** DOCKER SWARM NODES ***************** - {% for node in swarm_info.nodes %} - Node name: {{ node.Hostname }} - Availability: {{ node.Availability }} - ManagerStatus: {{ node.ManagerStatus }} - Status: {{ node.Status }} - {% endfor %} +- ansible.builtin.debug: + msg: | + ***************** DOCKER SWARM INFO ***************** + can_talk_to_docker: {{ swarm_info.can_talk_to_docker }} + docker_swarm_active: {{ swarm_info.docker_swarm_active }} + docker_swarm_manager: {{ swarm_info.docker_swarm_manager }} + failed: {{ swarm_info.failed }} + ***************** DOCKER SWARM NODES ***************** + {% for node in swarm_info.nodes %} + Node name: {{ node.Hostname }} + Availability: {{ node.Availability }} + ManagerStatus: {{ node.ManagerStatus }} + Status: {{ node.Status }} + {% endfor %} - - name: Running HTTP GET - get_url: - url: "https://192.168.0.120/{{ item }}/" - dest: /tmp/value - validate_certs: no - register: output - ignore_errors: yes - with_items: - - "dashboard" - - "filebrowser" - - "portainer" - - "admin" - - "grafana" - - "prometheus" - - "jellyfin" - - "nextcloud" - loop_control: - label: "{{ item }}" +- name: Running HTTP GET + ansible.builtin.get_url: + url: "https://192.168.0.120/{{ item }}/" + dest: /tmp/value + validate_certs: no + register: output + ignore_errors: yes + with_items: + - "dashboard" + - "filebrowser" + - "portainer" + - "admin" + - "grafana" + - "prometheus" + - "jellyfin" + - "nextcloud" + loop_control: + label: "{{ item }}" - - debug: - msg: | - {{ "{:<35} {}".format('URL', 'HTTP RESPONCE CODE') }} +- ansible.builtin.debug: + msg: | + {{ "{:<35} {}".format('URL', 'HTTP RESPONCE CODE') }} - {% for item in output.results %} - {{ "{:<40} {}".format(item.url, item.status_code) }} - {% endfor %} + {% for item in output.results %} + {{ "{:<40} {}".format(item.url, item.status_code) }} + {% endfor %} diff --git a/tasks/ufw.yml b/tasks/ufw.yml index 995f644..6ca9058 100644 --- a/tasks/ufw.yml +++ b/tasks/ufw.yml @@ -15,45 +15,43 @@ - 53 - 67 -- block: - # https://github.com/moby/moby/issues/4737#issuecomment-419705925 - - name: Append custom rules in /etc/ufw/after.rules - blockinfile: - dest: /etc/ufw/after.rules - block: "{{ lookup('template', 'templates/override_ufw_rules.j2' ) }}" - marker: "#{mark} ANSIBLE MANAGED BLOCK" +# https://github.com/moby/moby/issues/4737#issuecomment-419705925 +- name: Append custom rules in /etc/ufw/after.rules + ansible.builtin.blockinfile: + dest: /etc/ufw/after.rules + block: "{{ lookup('template', 'templates/override_ufw_rules.j2' ) }}" + marker: "#{mark} ANSIBLE MANAGED BLOCK" - - name: Set DEFAULT_FORWARD_POLICY=DROP in /etc/default/ufw - lineinfile: - path: /etc/default/ufw - regexp: '^DEFAULT_FORWARD_POLICY(.*)$' - line: 'DEFAULT_FORWARD_POLICY="DROP"' - backup: yes - backrefs: yes +- name: Set DEFAULT_FORWARD_POLICY=DROP in /etc/default/ufw + ansible.builtin.lineinfile: + path: /etc/default/ufw + regexp: '^DEFAULT_FORWARD_POLICY(.*)$' + line: 'DEFAULT_FORWARD_POLICY="DROP"' + backup: yes + backrefs: yes - - name: Set IPV6=no in /etc/default/ufw - lineinfile: - path: /etc/default/ufw - regexp: '^IPV6=(.*)$' - line: 'IPV6=no' - backup: yes - backrefs: yes +- name: Set IPV6=no in /etc/default/ufw + ansible.builtin.lineinfile: + path: /etc/default/ufw + regexp: '^IPV6=(.*)$' + line: 'IPV6=no' + backup: yes + backrefs: yes - - name: Allow selected tcp ports - ufw: - rule: allow - port: "{{ item }}" - proto: tcp - with_items: "{{ allow_tcp_ports }}" +- name: Allow selected tcp ports + community.general.ufw: + rule: allow + port: "{{ item }}" + proto: tcp + with_items: "{{ allow_tcp_ports }}" - - name: Allow selected udp ports - ufw: - rule: allow - port: "{{ item }}" - proto: udp - with_items: "{{ allow_udp_ports }}" +- name: Allow selected udp ports + ufw: + rule: allow + port: "{{ item }}" + proto: udp + with_items: "{{ allow_udp_ports }}" - - name: Enable ufw - ufw: - state: enabled - become: yes +- name: Enable ufw + ufw: + state: enabled diff --git a/vars.yml b/vars.yml index 4e85def..d2a0420 100644 --- a/vars.yml +++ b/vars.yml @@ -15,68 +15,6 @@ services: # Service's docker stack files copies in this location. It should end with slash services_base_dir_location: /opt/services/ -pkgs: - - "neofetch" - - "net-tools" - - "iotop" - - "blktrace" - - "ethtool" - - "nmap" - - "socat" - - "bridge-utils" - - "conntrack" - - "python3-scapy" - - "wipe" - - "htop" - - "screen" - - "traceroute" - - "ssh" - - "secure-delete" - - "pwgen" - - "tree" - - "macchanger" - - "unzip" - - "p7zip-full" - - "apt-transport-https" - - "ca-certificates" - - "gnupg" - - "curl" - - "wireless-tools" - - "openvpn" - - "python3-pip" - - "openssl" - - "aircrack-ng" - - "nmap" - - "hostapd" - - "dsniff" - - "libpcap-dev" - - "libusb-1.0-0" - - "libnetfilter-queue-dev" - - "build-essential" - - "golang" - - "gettext" - - "dhcpcd5" - - "isc-dhcp-server" - - "git" - - "libusb-1.0-0-dev" - - "jq" - - "python-setuptools" - - "python3-distutils" - - "linux-modules-extra-raspi" - -snaps: - - ngrok - -pypi: - - requests - - beautifulsoup4 - - ansible - - docker-compose - - setuptools - - jsondiff - - pyyaml - - docker - # Docker enable_userns_remap: false enable_docker_live_restore: false @@ -84,23 +22,16 @@ enable_docker_swarm_metrics: true enable_docker_swarm_mode: true docker_swarm_advertise_addr: 192.168.0.120 -# Run any custom scripts -scripts: - dotfiles: https://raw.githubusercontent.com/veerendra2/dotfiles/master/install.sh - -# Do all operations with this user(This user has to be sudoer) -run_user: "{{ ansible_env.USER }}" - -# Github user's ssh public keys -github_username_keys: https://github.com/veerendra2.keys - # Reboot after running tasks in tasks/prepare-pi.yml reboot_after_pi_preparation: true +# install fan.py script to control fan speed +install_fan_script: true + # Mount partions configuration in /etc/fstab disk_mount_dirs: # [DISK_PARTITION]: [MOUNT DIRECTORY] - /dev/sda1: /media/disk1 # Backup disk + # /dev/sda1: /media/disk1 # Backup disk /dev/sdb1: /media/disk2 # Main disk for nextcloud, filebrowser, jellyfin and postgres # Pi power optimization setttings From baf2e5402b36c069a27ec50bb67b3128624196da Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Tue, 29 Aug 2023 21:07:52 +0200 Subject: [PATCH 03/12] 80 Move torrent stack services --- .../{torrent/jackett => jacket}/.env_jackett | 0 .../config}/ServerConfig.json | 0 .../docker-stack.yml} | 20 ++++----------- services/qbittorrent/.vpn_ip | 1 + services/{torrent => qbittorrent}/README.md | 0 .../docker-stack.yml} | 1 - services/{torrent => qbittorrent}/ip-test.sh | 0 .../qbittorrent/.env_qbittorrent | 0 .../qbittorrent/qBittorrent.conf | 0 .../wireguard/.env_wireguard | 0 .../wireguard/dante-server/danted.conf | 0 .../wireguard/dante-server/install.sh | 0 .../wireguard/dante-server/run.sh | 0 services/{torrent => }/radarr/.env_radarr | 0 .../radarr => radarr/config}/config.xml | 0 .../docker-stack.yml} | 25 ++++--------------- services/{torrent => }/sonarr/.env_sonarr | 0 .../sonarr => sonarr/config}/config.xml | 0 .../docker-stack.yml} | 15 +++-------- tasks/deploy-services.yml | 1 - vars.yml | 8 ++++-- 21 files changed, 21 insertions(+), 50 deletions(-) rename services/{torrent/jackett => jacket}/.env_jackett (100%) rename services/{torrent/jackett => jacket/config}/ServerConfig.json (100%) rename services/{torrent/docker-stack-jackett.yml => jacket/docker-stack.yml} (65%) create mode 100644 services/qbittorrent/.vpn_ip rename services/{torrent => qbittorrent}/README.md (100%) rename services/{torrent/docker-stack-qbittorrent.yml => qbittorrent/docker-stack.yml} (96%) rename services/{torrent => qbittorrent}/ip-test.sh (100%) rename services/{torrent => qbittorrent}/qbittorrent/.env_qbittorrent (100%) rename services/{torrent => qbittorrent}/qbittorrent/qBittorrent.conf (100%) rename services/{torrent => qbittorrent}/wireguard/.env_wireguard (100%) rename services/{torrent => qbittorrent}/wireguard/dante-server/danted.conf (100%) rename services/{torrent => qbittorrent}/wireguard/dante-server/install.sh (100%) rename services/{torrent => qbittorrent}/wireguard/dante-server/run.sh (100%) rename services/{torrent => }/radarr/.env_radarr (100%) rename services/{torrent/radarr => radarr/config}/config.xml (100%) rename services/{torrent/docker-stack-radarr.yml => radarr/docker-stack.yml} (59%) rename services/{torrent => }/sonarr/.env_sonarr (100%) rename services/{torrent/sonarr => sonarr/config}/config.xml (100%) rename services/{torrent/docker-stack-sonarr.yml => sonarr/docker-stack.yml} (74%) diff --git a/services/torrent/jackett/.env_jackett b/services/jacket/.env_jackett similarity index 100% rename from services/torrent/jackett/.env_jackett rename to services/jacket/.env_jackett diff --git a/services/torrent/jackett/ServerConfig.json b/services/jacket/config/ServerConfig.json similarity index 100% rename from services/torrent/jackett/ServerConfig.json rename to services/jacket/config/ServerConfig.json diff --git a/services/torrent/docker-stack-jackett.yml b/services/jacket/docker-stack.yml similarity index 65% rename from services/torrent/docker-stack-jackett.yml rename to services/jacket/docker-stack.yml index d8fe1dc..4a0267d 100644 --- a/services/torrent/docker-stack-jackett.yml +++ b/services/jacket/docker-stack.yml @@ -1,19 +1,10 @@ --- -# https://dust6765.gitbook.io/raspberrypi-home-server/services/torrent-stack -version: "3.8" +version: 3.8 networks: network_private: external: true -volumes: - jackett: - driver: local - driver_opts: - o: bind - type: none - device: /media/disk2/volumes/jackett - services: jackett: image: linuxserver/jackett:arm64v8-0.21.568 @@ -33,12 +24,11 @@ services: - traefik.http.services.jackett.loadbalancer.server.port=9117 hostname: jackett env_file: - - ./jackett/.env_jackett - - .vpn_ip + - .env_jackett networks: - network_private volumes: - - jackett:/config - - ./jackett/ServerConfig.json:/config/Jackett/ServerConfig.json - - ./ip-test.sh:/opt/ip-test.sh + - ./config/ServerConfig.json:/config/Jackett/ServerConfig.json + # Change below + - /media/disk2/volumes/jackett:/config - /media/disk2/downloads/torrents:/opt/torrents diff --git a/services/qbittorrent/.vpn_ip b/services/qbittorrent/.vpn_ip new file mode 100644 index 0000000..5a25519 --- /dev/null +++ b/services/qbittorrent/.vpn_ip @@ -0,0 +1 @@ +VPN_IP=144.24.143.4 \ No newline at end of file diff --git a/services/torrent/README.md b/services/qbittorrent/README.md similarity index 100% rename from services/torrent/README.md rename to services/qbittorrent/README.md diff --git a/services/torrent/docker-stack-qbittorrent.yml b/services/qbittorrent/docker-stack.yml similarity index 96% rename from services/torrent/docker-stack-qbittorrent.yml rename to services/qbittorrent/docker-stack.yml index 21df49f..bee8229 100644 --- a/services/torrent/docker-stack-qbittorrent.yml +++ b/services/qbittorrent/docker-stack.yml @@ -1,5 +1,4 @@ --- -# https://dust6765.gitbook.io/raspberrypi-home-server/services/torrent-stack version: "3.8" networks: diff --git a/services/torrent/ip-test.sh b/services/qbittorrent/ip-test.sh similarity index 100% rename from services/torrent/ip-test.sh rename to services/qbittorrent/ip-test.sh diff --git a/services/torrent/qbittorrent/.env_qbittorrent b/services/qbittorrent/qbittorrent/.env_qbittorrent similarity index 100% rename from services/torrent/qbittorrent/.env_qbittorrent rename to services/qbittorrent/qbittorrent/.env_qbittorrent diff --git a/services/torrent/qbittorrent/qBittorrent.conf b/services/qbittorrent/qbittorrent/qBittorrent.conf similarity index 100% rename from services/torrent/qbittorrent/qBittorrent.conf rename to services/qbittorrent/qbittorrent/qBittorrent.conf diff --git a/services/torrent/wireguard/.env_wireguard b/services/qbittorrent/wireguard/.env_wireguard similarity index 100% rename from services/torrent/wireguard/.env_wireguard rename to services/qbittorrent/wireguard/.env_wireguard diff --git a/services/torrent/wireguard/dante-server/danted.conf b/services/qbittorrent/wireguard/dante-server/danted.conf similarity index 100% rename from services/torrent/wireguard/dante-server/danted.conf rename to services/qbittorrent/wireguard/dante-server/danted.conf diff --git a/services/torrent/wireguard/dante-server/install.sh b/services/qbittorrent/wireguard/dante-server/install.sh similarity index 100% rename from services/torrent/wireguard/dante-server/install.sh rename to services/qbittorrent/wireguard/dante-server/install.sh diff --git a/services/torrent/wireguard/dante-server/run.sh b/services/qbittorrent/wireguard/dante-server/run.sh similarity index 100% rename from services/torrent/wireguard/dante-server/run.sh rename to services/qbittorrent/wireguard/dante-server/run.sh diff --git a/services/torrent/radarr/.env_radarr b/services/radarr/.env_radarr similarity index 100% rename from services/torrent/radarr/.env_radarr rename to services/radarr/.env_radarr diff --git a/services/torrent/radarr/config.xml b/services/radarr/config/config.xml similarity index 100% rename from services/torrent/radarr/config.xml rename to services/radarr/config/config.xml diff --git a/services/torrent/docker-stack-radarr.yml b/services/radarr/docker-stack.yml similarity index 59% rename from services/torrent/docker-stack-radarr.yml rename to services/radarr/docker-stack.yml index 353b7a0..4f79cf0 100644 --- a/services/torrent/docker-stack-radarr.yml +++ b/services/radarr/docker-stack.yml @@ -1,19 +1,10 @@ --- -# https://dust6765.gitbook.io/raspberrypi-home-server/services/torrent-stack -version: "3.8" +version: 3.8 networks: network_private: external: true -volumes: - radarr: - driver: local - driver_opts: - o: bind - type: none - device: /media/disk2/volumes/radarr - services: radarr: image: linuxserver/radarr:arm64v8-4.6.4 @@ -33,17 +24,11 @@ services: - traefik.http.services.radarr.loadbalancer.server.port=7878 hostname: radarr env_file: - - ./radarr/.env_radarr - - .vpn_ip + - .env_radarr networks: - network_private volumes: - - radarr:/config - - ./radarr/config.xml:/config/config.xml - - ./ip-test.sh:/opt/ip-test.sh + - ./config/config.xml:/config/config.xml + # Change below + - /media/disk2/volumes/radarr:/config - /media/disk2/downloads:/downloads - # healthcheck: - # test: ["CMD", "/opt/ip-test.sh"] - # interval: 2m - # timeout: 10s - # retries: 3 diff --git a/services/torrent/sonarr/.env_sonarr b/services/sonarr/.env_sonarr similarity index 100% rename from services/torrent/sonarr/.env_sonarr rename to services/sonarr/.env_sonarr diff --git a/services/torrent/sonarr/config.xml b/services/sonarr/config/config.xml similarity index 100% rename from services/torrent/sonarr/config.xml rename to services/sonarr/config/config.xml diff --git a/services/torrent/docker-stack-sonarr.yml b/services/sonarr/docker-stack.yml similarity index 74% rename from services/torrent/docker-stack-sonarr.yml rename to services/sonarr/docker-stack.yml index acf196d..b106962 100644 --- a/services/torrent/docker-stack-sonarr.yml +++ b/services/sonarr/docker-stack.yml @@ -1,6 +1,5 @@ --- -# https://dust6765.gitbook.io/raspberrypi-home-server/services/torrent-stack -version: "3.8" +version: 3.8 networks: network_private: @@ -33,17 +32,11 @@ services: - traefik.http.services.sonarr.loadbalancer.server.port=8989 hostname: sonarr env_file: - - ./sonarr/.env_sonarr - - .vpn_ip + - .env_sonarr networks: - network_private volumes: - - sonarr:/config - ./sonarr/config.xml:/config/config.xml - - ./ip-test.sh:/opt/ip-test.sh + # Change below + - /media/disk2/volumes/sonarr:/config - /media/disk2/downloads:/downloads - # healthcheck: - # test: ["CMD", "/opt/ip-test.sh"] - # interval: 2m - # timeout: 10s - # retries: 3 diff --git a/tasks/deploy-services.yml b/tasks/deploy-services.yml index fdf2fc3..06373a5 100644 --- a/tasks/deploy-services.yml +++ b/tasks/deploy-services.yml @@ -34,7 +34,6 @@ name: traefik compose: - "{{ [services_base_dir_location, 'traefik', 'network.yml'] | path_join }}" - when: "'traefik' in services" - name: Deploy service stacks community.docker.docker_stack: diff --git a/vars.yml b/vars.yml index d2a0420..1001a58 100644 --- a/vars.yml +++ b/vars.yml @@ -9,8 +9,12 @@ services: - nextcloud # - pihole - portainer - - traefik - - torrent + - qbittorrent + - radarr + - sonarr + - rest-server + - vaultwarden + - searxng # Service's docker stack files copies in this location. It should end with slash services_base_dir_location: /opt/services/ From 085b4c8fb2a4c5f345bc361b3f5bacb432786a35 Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Tue, 29 Aug 2023 23:05:48 +0200 Subject: [PATCH 04/12] 80 Refactor volumes --- README.md | 22 ++++++++------- services/databases/docker-stack.yml | 7 ++--- services/filebrowser/docker-stack.yml | 11 +++----- services/homer/docker-stack.yml | 2 +- services/jacket/docker-stack.yml | 3 +- services/jellyfin/docker-stack.yml | 12 +++----- services/monitoring/docker-stack.yml | 6 ++-- services/nextcloud/docker-stack.yml | 2 +- services/pihole/docker-stack.yml | 5 +--- services/portainer/docker-stack.yml | 8 ++---- .../{wireguard => }/.env_wireguard | 0 services/qbittorrent/README.md | 2 +- .../{qbittorrent => config}/.env_qbittorrent | 0 .../{qbittorrent => config}/qBittorrent.conf | 0 .../{wireguard => }/dante-server/danted.conf | 0 .../{wireguard => }/dante-server/install.sh | 0 .../{wireguard => }/dante-server/run.sh | 0 services/qbittorrent/docker-stack.yml | 28 ++++++------------- services/qbittorrent/ip-test.sh | 5 ++-- services/radarr/docker-stack.yml | 1 - .../searxng/{searxng => config}/settings.yml | 0 .../searxng/{searxng => config}/uwsgi.ini | 0 services/searxng/docker-stack.yml | 2 +- services/sonarr/docker-stack.yml | 13 ++------- services/traefik/networks.yml | 2 +- services/vaultwarden/docker-stack.yml | 4 +-- vars.yml | 14 +++++----- 27 files changed, 55 insertions(+), 94 deletions(-) rename services/qbittorrent/{wireguard => }/.env_wireguard (100%) rename services/qbittorrent/{qbittorrent => config}/.env_qbittorrent (100%) rename services/qbittorrent/{qbittorrent => config}/qBittorrent.conf (100%) rename services/qbittorrent/{wireguard => }/dante-server/danted.conf (100%) rename services/qbittorrent/{wireguard => }/dante-server/install.sh (100%) rename services/qbittorrent/{wireguard => }/dante-server/run.sh (100%) rename services/searxng/{searxng => config}/settings.yml (100%) rename services/searxng/{searxng => config}/uwsgi.ini (100%) diff --git a/README.md b/README.md index 6521ff0..e46f8f8 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ ![GitHub forks](https://img.shields.io/github/forks/veerendra2/raspberrypi-homeserver?style=plastic) ![GitHub issues](https://img.shields.io/github/issues/veerendra2/raspberrypi-homeserver?style=plastic) ![GitHub release (release name instead of tag name)](https://img.shields.io/github/v/release/veerendra2/raspberrypi-homeserver?include_prereleases&style=plastic) -# Self-host Docker Swarm Stacks -> _Previuosly known as "Raspberry Pi homeserver"_ +# Raspberry Pi Homeserver +

-A collection of applications and tools +A collection of self-host docker swarm stacks

@@ -195,6 +195,8 @@ ## Getting Started > Refer [Gitbook Docs](https://dust6765.gitbook.io/raspberrypi-home-server/) for more details and how to deploy manually +Ansible automation works well, if all services are intended to deploy on single box. Since I have only one machine, don't have to worry about the docker volumes, all of my docker volumes stored on single SSD mounted to host. + * Follow prerequisite [manual steps](https://dust6765.gitbook.io/raspberrypi-home-server/settings/manual-steps) to prepare Pi * Browse [vars.yml](./vars.yml) to configuration @@ -215,12 +217,12 @@ $ ansible-playbook main.yml constraints: [node.role == manager] ... ``` -* Currently ~~I'm using IP address `192.168.0.120` to access services, change services configs if you have a domain~~ using duckdns sub-domain. Refer my [blog post](https://veerendra2.github.io/traefik-https) to get more info. +* Currently I'm using duckdns sub-domain. Refer my [blog post](https://veerendra2.github.io/traefik-https) to get more info. ## Related Blogs -* https://veerendra2.github.io/portainer-vs-yacht -* https://veerendra2.github.io/pihole-dhcp-relay -* https://veerendra2.github.io/wireguard-qbittorrent-docker-swarm-1 -* https://veerendra2.github.io/wireguard-qbittorrent-docker-swarm-2 -* https://veerendra2.github.io/traefik-https -* https://dev.to/veerendra2/how-to-deploy-rest-serverrestic-on-docker-swarm-behind-traefik-reverse-proxy-4a8h \ No newline at end of file +* [Portainer vs Yacht](https://veerendra2.github.io/portainer-vs-yacht) +* [Pi-hole with DHCP Relay in Docker](https://veerendra2.github.io/pihole-dhcp-relay) +* [Wireguard VPN and BitTorrent on Docker Swarm (Part 1)](https://veerendra2.github.io/wireguard-qbittorrent-docker-swarm-1) +* [Wireguard VPN and BitTorrent on Docker Swarm (Part 2)](https://veerendra2.github.io/wireguard-qbittorrent-docker-swarm-2) +* [Traefik HTTPS Config with DuckDNS for Local Homeserver](https://veerendra2.github.io/traefik-https) +* [How to Deploy rest-server(Restic) on Docker Swarm Behind Traefik Reverse Proxy](https://dev.to/veerendra2/how-to-deploy-rest-serverrestic-on-docker-swarm-behind-traefik-reverse-proxy-4a8h) diff --git a/services/databases/docker-stack.yml b/services/databases/docker-stack.yml index 98742c1..bd144e8 100644 --- a/services/databases/docker-stack.yml +++ b/services/databases/docker-stack.yml @@ -1,6 +1,6 @@ --- # https://dust6765.gitbook.io/raspberrypi-home-server/services/databases -version: "3.8" +version: '3.8' networks: networks_public: @@ -8,9 +8,6 @@ networks: network_databases: external: true -volumes: - redis: - secrets: postgres_password: file: secrets/postgres_password.txt @@ -69,7 +66,7 @@ services: env_file: - .env_redis volumes: - - redis:/data + - /media/disk2/volumes/redis:/data networks: - network_databases secrets: diff --git a/services/filebrowser/docker-stack.yml b/services/filebrowser/docker-stack.yml index 11de19a..9f0f3fd 100644 --- a/services/filebrowser/docker-stack.yml +++ b/services/filebrowser/docker-stack.yml @@ -1,14 +1,11 @@ --- # https://dust6765.gitbook.io/raspberrypi-home-server/services/file-browser -version: "3.8" +version: '3.8' networks: network_public: external: true -volumes: - filebrowser: - services: filebrowser: image: filebrowser/filebrowser:v2.24.1 @@ -32,10 +29,10 @@ services: env_file: - .env_filebrowser volumes: - - /media/disk1:/srv/disk1 - - /media/disk2:/srv/disk2 - ./config/filebrowser.json:/.filebrowser.json - - filebrowser:/database + - /media/disk2/volumes/filebrowser:/database + - /media/disk2:/srv/disk2 + - /media/disk1:/srv/disk1 networks: network_public: diff --git a/services/homer/docker-stack.yml b/services/homer/docker-stack.yml index 5c8388f..43095bc 100644 --- a/services/homer/docker-stack.yml +++ b/services/homer/docker-stack.yml @@ -1,6 +1,6 @@ --- # https://dust6765.gitbook.io/raspberrypi-home-server/services/homer -version: "3.8" +version: '3.8' networks: network_public: diff --git a/services/jacket/docker-stack.yml b/services/jacket/docker-stack.yml index 4a0267d..7352d59 100644 --- a/services/jacket/docker-stack.yml +++ b/services/jacket/docker-stack.yml @@ -1,5 +1,5 @@ --- -version: 3.8 +version: '3.8' networks: network_private: @@ -29,6 +29,5 @@ services: - network_private volumes: - ./config/ServerConfig.json:/config/Jackett/ServerConfig.json - # Change below - /media/disk2/volumes/jackett:/config - /media/disk2/downloads/torrents:/opt/torrents diff --git a/services/jellyfin/docker-stack.yml b/services/jellyfin/docker-stack.yml index ac66148..392dc1e 100644 --- a/services/jellyfin/docker-stack.yml +++ b/services/jellyfin/docker-stack.yml @@ -1,10 +1,6 @@ --- # https://dust6765.gitbook.io/raspberrypi-home-server/services/jellyfin -version: "3.8" - -volumes: - config: - cache: +version: '3.8' networks: network_public: @@ -40,11 +36,11 @@ services: protocol: udp mode: host volumes: - - /media/disk2:/disk2:ro - - /media/disk2/volumes/jellyfin/config:/config - - /media/disk2/volumes/jellyfin/cache:/cache - ./config/network.xml:/config/config/network.xml - ./config/system.xml:/config/config/system.xml - /etc/localtime:/etc/localtime:ro + - /media/disk2:/disk2:ro + - /media/disk2/volumes/jellyfin/config:/config + - /media/disk2/volumes/jellyfin/cache:/cache networks: - network_public diff --git a/services/monitoring/docker-stack.yml b/services/monitoring/docker-stack.yml index 756c340..bc1ab13 100644 --- a/services/monitoring/docker-stack.yml +++ b/services/monitoring/docker-stack.yml @@ -1,6 +1,6 @@ --- # https://dust6765.gitbook.io/raspberrypi-home-server/services/monitoring -version: "3.8" +version: '3.8' networks: network_monitoring: @@ -36,7 +36,7 @@ services: hostname: prometheus volumes: - ./prometheus:/etc/prometheus - - prometheus:/prometheus + - /media/disk2/volumes/prometheus:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' @@ -71,7 +71,7 @@ services: - traefik.http.services.grafana.loadbalancer.server.port=3000 hostname: grafana volumes: - - grafana:/var/lib/grafana + - /media/disk2/volumes/grafana:/var/lib/grafana - ./grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards - ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources env_file: diff --git a/services/nextcloud/docker-stack.yml b/services/nextcloud/docker-stack.yml index 3a821fc..1b25bcb 100644 --- a/services/nextcloud/docker-stack.yml +++ b/services/nextcloud/docker-stack.yml @@ -1,6 +1,6 @@ --- # https://dust6765.gitbook.io/raspberrypi-home-server/services/nextcloud -version: "3.8" +version: '3.8' networks: network_public: diff --git a/services/pihole/docker-stack.yml b/services/pihole/docker-stack.yml index b5f823d..bb11066 100644 --- a/services/pihole/docker-stack.yml +++ b/services/pihole/docker-stack.yml @@ -6,9 +6,6 @@ networks: network_public: external: true -volumes: - pihole: - secrets: pihole_admin_password: file: ./secrets/pihole_admin_password.txt @@ -40,9 +37,9 @@ services: - 127.0.0.1 - 1.1.1.1 volumes: - - pihole:/etc - ./pihole/custom.list:/etc/pihole/custom.list:ro - /etc/resolv.conf:/etc/resolv.conf:ro + - /media/disk2/volumes/pihole:/etc secrets: - pihole_admin_password networks: diff --git a/services/portainer/docker-stack.yml b/services/portainer/docker-stack.yml index 9f28b06..8c3343e 100644 --- a/services/portainer/docker-stack.yml +++ b/services/portainer/docker-stack.yml @@ -1,14 +1,10 @@ --- -# https://dust6765.gitbook.io/raspberrypi-home-server/services/portainer -version: "3.8" +version: '3.8' networks: network_public: external: true -volumes: - portainer: - secrets: portainer_admin_password: file: ./secrets/portainer_admin_password.txt @@ -41,7 +37,7 @@ services: - --admin-password-file=/run/secrets/portainer_admin_password volumes: - /var/run/docker.sock:/var/run/docker.sock - - portainer:/data + - /media/disk2/volumes/portainer:/data networks: - network_public secrets: diff --git a/services/qbittorrent/wireguard/.env_wireguard b/services/qbittorrent/.env_wireguard similarity index 100% rename from services/qbittorrent/wireguard/.env_wireguard rename to services/qbittorrent/.env_wireguard diff --git a/services/qbittorrent/README.md b/services/qbittorrent/README.md index 4994da3..efa2f13 100644 --- a/services/qbittorrent/README.md +++ b/services/qbittorrent/README.md @@ -1,4 +1,4 @@ -# Torrent Stack +# qBittorent + Wireguard * All torrent traffic proxied through `wireguard` container with `dante-server` SOCKS5 protocal. * Below docker services are configured with `healthchecks` that uses [`ip-test.sh`](./ip-test.sh) script to check current connection is secured or not. Set `vpn_ip` variable in `vars.yml` to check external ip is this ip or add `VPN_IP=` environmental variable in `.vpn_ip`. * `qBittorrnet` + `wiregard` -> `docker-stack-qbittorrent.yml` diff --git a/services/qbittorrent/qbittorrent/.env_qbittorrent b/services/qbittorrent/config/.env_qbittorrent similarity index 100% rename from services/qbittorrent/qbittorrent/.env_qbittorrent rename to services/qbittorrent/config/.env_qbittorrent diff --git a/services/qbittorrent/qbittorrent/qBittorrent.conf b/services/qbittorrent/config/qBittorrent.conf similarity index 100% rename from services/qbittorrent/qbittorrent/qBittorrent.conf rename to services/qbittorrent/config/qBittorrent.conf diff --git a/services/qbittorrent/wireguard/dante-server/danted.conf b/services/qbittorrent/dante-server/danted.conf similarity index 100% rename from services/qbittorrent/wireguard/dante-server/danted.conf rename to services/qbittorrent/dante-server/danted.conf diff --git a/services/qbittorrent/wireguard/dante-server/install.sh b/services/qbittorrent/dante-server/install.sh similarity index 100% rename from services/qbittorrent/wireguard/dante-server/install.sh rename to services/qbittorrent/dante-server/install.sh diff --git a/services/qbittorrent/wireguard/dante-server/run.sh b/services/qbittorrent/dante-server/run.sh similarity index 100% rename from services/qbittorrent/wireguard/dante-server/run.sh rename to services/qbittorrent/dante-server/run.sh diff --git a/services/qbittorrent/docker-stack.yml b/services/qbittorrent/docker-stack.yml index bee8229..4412e4f 100644 --- a/services/qbittorrent/docker-stack.yml +++ b/services/qbittorrent/docker-stack.yml @@ -1,5 +1,5 @@ --- -version: "3.8" +version: '3.8' networks: network_private: @@ -7,14 +7,6 @@ networks: network_public: external: true -volumes: - qbitorrent: - driver: local - driver_opts: - o: bind - type: none - device: /media/disk2/volumes/qbitorrent - services: wireguard: image: linuxserver/wireguard:arm64v8-1.0.20210914-legacy @@ -30,7 +22,7 @@ services: - traefik.enable=false hostname: wireguard env_file: - - ./wireguard/.env_wireguard + - .env_wireguard networks: - network_public - network_private @@ -38,10 +30,10 @@ services: - NET_ADMIN volumes: - /lib/modules:/lib/modules + - ./dante-server/danted.conf:/etc/danted.conf + - ./dante-server/install.sh:/custom-cont-init.d/install.sh:ro + - ./dante-server/run.sh:/custom-services.d/run.sh:ro - /media/disk2/volumes/secrets/wg0.conf:/config/wg0.conf - - ./wireguard/dante-server/danted.conf:/etc/danted.conf - - ./wireguard/dante-server/install.sh:/custom-cont-init.d/install.sh:ro - - ./wireguard/dante-server/run.sh:/custom-services.d/run.sh:ro sysctls: - net.ipv4.conf.all.src_valid_mark=1 - net.ipv6.conf.all.disable_ipv6=0 @@ -66,21 +58,17 @@ services: - traefik.http.services.qbittorrent.loadbalancer.server.port=8080 hostname: qbittorrent env_file: - - ./qbittorrent/.env_qbittorrent + - .env_qbittorrent - .vpn_ip networks: - network_private volumes: - - qbitorrent:/config - - ./qbittorrent/qBittorrent.conf:/config/qBittorrent/qBittorrent.conf + - ./config/qBittorrent.conf:/config/qBittorrent/qBittorrent.conf - ./ip-test.sh:/opt/ip-test.sh + - /media/disk2/volumes/qbitorrent:/config - /media/disk2/downloads:/downloads # healthcheck: # test: ["CMD", "/opt/ip-test.sh"] # interval: 2m # timeout: 10s # retries: 3 - - - - diff --git a/services/qbittorrent/ip-test.sh b/services/qbittorrent/ip-test.sh index c70864c..e4d7117 100755 --- a/services/qbittorrent/ip-test.sh +++ b/services/qbittorrent/ip-test.sh @@ -1,10 +1,9 @@ #!/bin/bash -# Author: veerendra2 # Description: A simple script to test current ip is given vpn ip. # Used as healthcheck in docker service -# httpbin.org's ip (supports HTTP, since no dns config exists in containers) -HTTPBIN_ORG_IP=54.204.94.184 +# c's ip (supports HTTP, since no dns config exists in containers) +HTTPBIN_ORG_IP=3.94.140.209 MY_IP=`curl -s -x socks5://wireguard:1080 http://$HTTPBIN_ORG_IP/ip | jq --raw-output .origin` if [ "$MY_IP" == "$VPN_IP" ]; diff --git a/services/radarr/docker-stack.yml b/services/radarr/docker-stack.yml index 4f79cf0..3bb00e2 100644 --- a/services/radarr/docker-stack.yml +++ b/services/radarr/docker-stack.yml @@ -29,6 +29,5 @@ services: - network_private volumes: - ./config/config.xml:/config/config.xml - # Change below - /media/disk2/volumes/radarr:/config - /media/disk2/downloads:/downloads diff --git a/services/searxng/searxng/settings.yml b/services/searxng/config/settings.yml similarity index 100% rename from services/searxng/searxng/settings.yml rename to services/searxng/config/settings.yml diff --git a/services/searxng/searxng/uwsgi.ini b/services/searxng/config/uwsgi.ini similarity index 100% rename from services/searxng/searxng/uwsgi.ini rename to services/searxng/config/uwsgi.ini diff --git a/services/searxng/docker-stack.yml b/services/searxng/docker-stack.yml index 328300d..98b9c19 100644 --- a/services/searxng/docker-stack.yml +++ b/services/searxng/docker-stack.yml @@ -27,7 +27,7 @@ services: env_file: - .env_searxng volumes: - - ./searxng:/etc/searxng:rw + - ./config:/etc/searxng:rw networks: - network_public - network_databases diff --git a/services/sonarr/docker-stack.yml b/services/sonarr/docker-stack.yml index b106962..ad33594 100644 --- a/services/sonarr/docker-stack.yml +++ b/services/sonarr/docker-stack.yml @@ -1,18 +1,10 @@ --- -version: 3.8 +version: '3.8' networks: network_private: external: true -volumes: - sonarr: - driver: local - driver_opts: - o: bind - type: none - device: /media/disk2/volumes/sonarr - services: sonarr: image: linuxserver/sonarr:arm64v8-3.0.10 @@ -36,7 +28,6 @@ services: networks: - network_private volumes: - - ./sonarr/config.xml:/config/config.xml - # Change below + - ./config/config.xml:/config/config.xml - /media/disk2/volumes/sonarr:/config - /media/disk2/downloads:/downloads diff --git a/services/traefik/networks.yml b/services/traefik/networks.yml index e8c6e91..926af86 100644 --- a/services/traefik/networks.yml +++ b/services/traefik/networks.yml @@ -1,4 +1,4 @@ -version: "3.8" +version: 3.8 services: networks_scratch: diff --git a/services/vaultwarden/docker-stack.yml b/services/vaultwarden/docker-stack.yml index bfdc3c2..834cf6e 100644 --- a/services/vaultwarden/docker-stack.yml +++ b/services/vaultwarden/docker-stack.yml @@ -1,4 +1,4 @@ -version: "3.8" +version: '3.8' networks: network_public: @@ -42,8 +42,8 @@ services: env_file: - .env_vaultwarden volumes: - - /media/disk2/volumes/vaultwarden:/data:rw - ./scripts:/etc/vaultwarden.d + - /media/disk2/volumes/vaultwarden:/data:rw networks: - network_public - network_databases diff --git a/vars.yml b/vars.yml index 1001a58..db4b1ae 100644 --- a/vars.yml +++ b/vars.yml @@ -7,14 +7,14 @@ services: - jellyfin - monitoring - nextcloud - # - pihole - - portainer - - qbittorrent - - radarr - - sonarr - rest-server - - vaultwarden - - searxng + - qbittorrent + # - pihole + # - portainer + # - radarr + # - sonarr + # - vaultwarden + # - searxng # Service's docker stack files copies in this location. It should end with slash services_base_dir_location: /opt/services/ From 3cb027c48a23a6dcc18f6b07ea7fd76164e55378 Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Wed, 30 Aug 2023 23:42:10 +0200 Subject: [PATCH 05/12] 80 Add duckdns domain in compose files --- services/README.md | 6 ------ services/filebrowser/docker-stack.yml | 2 +- services/homer/docker-stack.yml | 2 +- services/jacket/README.md | 4 ++++ services/jacket/docker-stack.yml | 2 +- services/jellyfin/docker-stack.yml | 2 +- services/monitoring/docker-stack.yml | 4 ++-- services/nextcloud/docker-stack.yml | 2 +- services/pihole/docker-stack.yml | 2 +- services/portainer/docker-stack.yml | 2 +- services/qbittorrent/docker-stack.yml | 2 +- services/radarr/README.md | 4 ++++ services/radarr/docker-stack.yml | 2 +- services/rest-server/docker-stack.yml | 2 +- services/searxng/docker-stack.yml | 2 +- services/sonarr/README.md | 4 ++++ services/sonarr/docker-stack.yml | 2 +- services/traefik/docker-stack.yml | 2 +- services/vaultwarden/docker-stack.yml | 4 ++-- 19 files changed, 29 insertions(+), 23 deletions(-) create mode 100644 services/jacket/README.md create mode 100644 services/radarr/README.md create mode 100644 services/sonarr/README.md diff --git a/services/README.md b/services/README.md index 46d5a11..5bceb05 100644 --- a/services/README.md +++ b/services/README.md @@ -1,7 +1 @@ # Docker Swarm Services -> Refer [Gitbook Docs](https://dust6765.gitbook.io/raspberrypi-home-server/services) - -**NOTE:** Export `DOMAIN` environmental variable before deploying services - ```bash - $ export DOMAIN=mydomain.com - ``` \ No newline at end of file diff --git a/services/filebrowser/docker-stack.yml b/services/filebrowser/docker-stack.yml index 9f0f3fd..d5f62ac 100644 --- a/services/filebrowser/docker-stack.yml +++ b/services/filebrowser/docker-stack.yml @@ -21,7 +21,7 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.filebrowser.tls=true - - traefik.http.routers.filebrowser.rule=Host(`${DOMAIN}`) && PathPrefix(`/filebrowser`) + - traefik.http.routers.filebrowser.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/filebrowser`) - traefik.http.routers.filebrowser.middlewares=filebrowser-stripprefix - traefik.http.middlewares.filebrowser-stripprefix.stripprefix.prefixes=/filebrowser - traefik.http.services.filebrowser.loadbalancer.server.port=80 diff --git a/services/homer/docker-stack.yml b/services/homer/docker-stack.yml index 43095bc..bc9cbc6 100644 --- a/services/homer/docker-stack.yml +++ b/services/homer/docker-stack.yml @@ -20,7 +20,7 @@ services: labels: - "traefik.enable=true" - "traefik.docker.network=network_public" - - "traefik.http.routers.homer.rule=Host(`${DOMAIN}`) && PathPrefix(`/`)" + - "traefik.http.routers.homer.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/`)" - "traefik.http.routers.homer.tls=true" - "traefik.http.services.homer.loadbalancer.server.port=8080" hostname: homer diff --git a/services/jacket/README.md b/services/jacket/README.md new file mode 100644 index 0000000..6e8ccb5 --- /dev/null +++ b/services/jacket/README.md @@ -0,0 +1,4 @@ +# jacket +This stack requires `qBittorent` + `Wireguard` which should be up and running. + +* Deploy [qBittorrent + Wireguard](../qbittorrent/) diff --git a/services/jacket/docker-stack.yml b/services/jacket/docker-stack.yml index 7352d59..1eea633 100644 --- a/services/jacket/docker-stack.yml +++ b/services/jacket/docker-stack.yml @@ -20,7 +20,7 @@ services: - traefik.enable=true - traefik.docker.network=network_private - traefik.http.routers.jackett.tls=true - - traefik.http.routers.jackett.rule=Host(`${DOMAIN}`) && PathPrefix(`/jackett`) + - traefik.http.routers.jackett.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/jackett`) - traefik.http.services.jackett.loadbalancer.server.port=9117 hostname: jackett env_file: diff --git a/services/jellyfin/docker-stack.yml b/services/jellyfin/docker-stack.yml index 392dc1e..15d1ac6 100644 --- a/services/jellyfin/docker-stack.yml +++ b/services/jellyfin/docker-stack.yml @@ -21,7 +21,7 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.jellyfin.tls=true - - traefik.http.routers.jellyfin.rule=Host(`${DOMAIN}`) && PathPrefix(`/jellyfin`) + - traefik.http.routers.jellyfin.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/jellyfin`) - traefik.http.services.jellyfin.loadbalancer.server.port=8096 hostname: jellyfin env_file: diff --git a/services/monitoring/docker-stack.yml b/services/monitoring/docker-stack.yml index bc1ab13..52a5d5b 100644 --- a/services/monitoring/docker-stack.yml +++ b/services/monitoring/docker-stack.yml @@ -31,7 +31,7 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.prometheus.tls=true - - traefik.http.routers.prometheus.rule=Host(`${DOMAIN}`) && PathPrefix(`/prometheus`) + - traefik.http.routers.prometheus.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/prometheus`) - traefik.http.services.prometheus.loadbalancer.server.port=9090 hostname: prometheus volumes: @@ -65,7 +65,7 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.grafana.tls=true - - traefik.http.routers.grafana.rule=Host(`${DOMAIN}`) && PathPrefix(`/grafana`) + - traefik.http.routers.grafana.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/grafana`) - traefik.http.routers.grafana.middlewares=grafana-stripprefix - traefik.http.middlewares.grafana-stripprefix.stripprefix.prefixes=/grafana - traefik.http.services.grafana.loadbalancer.server.port=3000 diff --git a/services/nextcloud/docker-stack.yml b/services/nextcloud/docker-stack.yml index 1b25bcb..e10f5a9 100644 --- a/services/nextcloud/docker-stack.yml +++ b/services/nextcloud/docker-stack.yml @@ -37,7 +37,7 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.nextcloud.tls=true - - traefik.http.routers.nextcloud.rule=Host(`${DOMAIN}`) && PathPrefix(`/nextcloud`) + - traefik.http.routers.nextcloud.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/nextcloud`) - traefik.http.routers.nextcloud.middlewares=nextcloud-stripprefix - traefik.http.middlewares.nextcloud-stripprefix.stripprefix.prefixes=/nextcloud - traefik.http.services.nextcloud.loadbalancer.server.port=80 diff --git a/services/pihole/docker-stack.yml b/services/pihole/docker-stack.yml index bb11066..afbcef8 100644 --- a/services/pihole/docker-stack.yml +++ b/services/pihole/docker-stack.yml @@ -24,7 +24,7 @@ services: labels: - traefik.enable=true - traefik.docker.network=network_public - - traefik.http.routers.pihole.rule=Host(`${DOMAIN}`) && PathPrefix(`/admin`) + - traefik.http.routers.pihole.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/admin`) - traefik.http.routers.pihole.tls=true - traefik.http.services.pihole.loadbalancer.server.port=80 hostname: pihole diff --git a/services/portainer/docker-stack.yml b/services/portainer/docker-stack.yml index 8c3343e..e69f8a1 100644 --- a/services/portainer/docker-stack.yml +++ b/services/portainer/docker-stack.yml @@ -24,7 +24,7 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.portainer.tls=true" - - traefik.http.routers.portainer.rule=Host(`${DOMAIN}`) && PathPrefix(`/portainer`) + - traefik.http.routers.portainer.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/portainer`) - traefik.http.routers.portainer.middlewares=portainer-stripprefix - traefik.http.middlewares.portainer-stripprefix.stripprefix.prefixes=/portainer - traefik.http.services.portainer.loadbalancer.server.port=9000 diff --git a/services/qbittorrent/docker-stack.yml b/services/qbittorrent/docker-stack.yml index 4412e4f..2d66ec1 100644 --- a/services/qbittorrent/docker-stack.yml +++ b/services/qbittorrent/docker-stack.yml @@ -52,7 +52,7 @@ services: - traefik.enable=true - traefik.docker.network=network_private - traefik.http.routers.qbittorrent.tls=true - - traefik.http.routers.qbittorrent.rule=Host(`${DOMAIN}`) && PathPrefix(`/qbittorrent`) + - traefik.http.routers.qbittorrent.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/qbittorrent`) - traefik.http.routers.qbittorrent.middlewares=qbittorrent-stripprefix - traefik.http.middlewares.qbittorrent-stripprefix.stripprefix.prefixes=/qbittorrent - traefik.http.services.qbittorrent.loadbalancer.server.port=8080 diff --git a/services/radarr/README.md b/services/radarr/README.md new file mode 100644 index 0000000..bf6d6c9 --- /dev/null +++ b/services/radarr/README.md @@ -0,0 +1,4 @@ +# Radarr +This stack requires `qBittorent` + `Wireguard` which should be up and running. + +* Deploy [qBittorrent + Wireguard](../qbittorrent/) diff --git a/services/radarr/docker-stack.yml b/services/radarr/docker-stack.yml index 3bb00e2..87e77c6 100644 --- a/services/radarr/docker-stack.yml +++ b/services/radarr/docker-stack.yml @@ -20,7 +20,7 @@ services: - traefik.enable=true - traefik.docker.network=network_private - traefik.http.routers.radarr.tls=true - - traefik.http.routers.radarr.rule=Host(`${DOMAIN}`) && PathPrefix(`/radarr`) + - traefik.http.routers.radarr.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/radarr`) - traefik.http.services.radarr.loadbalancer.server.port=7878 hostname: radarr env_file: diff --git a/services/rest-server/docker-stack.yml b/services/rest-server/docker-stack.yml index 0197428..bf2e588 100644 --- a/services/rest-server/docker-stack.yml +++ b/services/rest-server/docker-stack.yml @@ -25,7 +25,7 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.rest-server.tls=true - - traefik.http.routers.rest-server.rule=Host(`${DOMAIN}`) && PathPrefix(`/restic`) + - traefik.http.routers.rest-server.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/restic`) - traefik.http.services.rest-server.loadbalancer.server.port=8000 hostname: rest-server user: 1000:1003 diff --git a/services/searxng/docker-stack.yml b/services/searxng/docker-stack.yml index 98b9c19..fa7d6cf 100644 --- a/services/searxng/docker-stack.yml +++ b/services/searxng/docker-stack.yml @@ -21,7 +21,7 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.searxng.tls=true - - traefik.http.routers.searxng.rule=Host(`${DOMAIN}`) && PathPrefix(`/searxng`) + - traefik.http.routers.searxng.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/searxng`) - traefik.http.services.searxng.loadbalancer.server.port=8080 hostname: searxng env_file: diff --git a/services/sonarr/README.md b/services/sonarr/README.md new file mode 100644 index 0000000..62843f4 --- /dev/null +++ b/services/sonarr/README.md @@ -0,0 +1,4 @@ +# Sonarr +This stack requires `qBittorent` + `Wireguard` which should be up and running. + +* Deploy [qBittorrent + Wireguard](../qbittorrent/) diff --git a/services/sonarr/docker-stack.yml b/services/sonarr/docker-stack.yml index ad33594..b3fdbff 100644 --- a/services/sonarr/docker-stack.yml +++ b/services/sonarr/docker-stack.yml @@ -20,7 +20,7 @@ services: - traefik.enable=true - traefik.docker.network=network_private - traefik.http.routers.sonarr.tls=true - - traefik.http.routers.sonarr.rule=Host(`${DOMAIN}`) && PathPrefix(`/sonarr`) + - traefik.http.routers.sonarr.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/sonarr`) - traefik.http.services.sonarr.loadbalancer.server.port=8989 hostname: sonarr env_file: diff --git a/services/traefik/docker-stack.yml b/services/traefik/docker-stack.yml index ed07779..9c64bf5 100644 --- a/services/traefik/docker-stack.yml +++ b/services/traefik/docker-stack.yml @@ -36,7 +36,7 @@ services: - traefik.http.routers.api.tls=true - traefik.http.routers.api.entrypoints=https - traefik.http.routers.api.tls.certresolver=httpResolver - - traefik.http.routers.api.rule=Host(`${DOMAIN}`) && PathPrefix(`/dashboard`) || Host(`${DOMAIN}`) && PathPrefix(`/api`) + - traefik.http.routers.api.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/dashboard`) || Host(`veeru.duckdns.org`) && PathPrefix(`/api`) - traefik.http.routers.api.service=api@internal - traefik.http.services.dummy.loadbalancer.server.port=9999 hostname: traefik diff --git a/services/vaultwarden/docker-stack.yml b/services/vaultwarden/docker-stack.yml index 834cf6e..29eb4a9 100644 --- a/services/vaultwarden/docker-stack.yml +++ b/services/vaultwarden/docker-stack.yml @@ -31,11 +31,11 @@ services: - traefik.enable=true - traefik.docker.network=network_public - traefik.http.routers.vaultwarden.tls=true - - traefik.http.routers.vaultwarden.rule=Host(`${DOMAIN}`) && PathPrefix(`/vaultwarden`) + - traefik.http.routers.vaultwarden.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/vaultwarden`) - traefik.http.routers.vaultwarden.service=vaultwarden - traefik.http.services.vaultwarden.loadbalancer.server.port=80 - traefik.http.routers.vaultwarden-websocket.tls=true - - traefik.http.routers.vaultwarden-websocket.rule=Host(`${DOMAIN}`) && Path(`/notifications/hub`) + - traefik.http.routers.vaultwarden-websocket.rule=Host(`veeru.duckdns.org`) && Path(`/notifications/hub`) - traefik.http.routers.vaultwarden-websocket.service=vaultwarden-websocket - traefik.http.services.vaultwarden-websocket.loadbalancer.server.port=3012 hostname: vaultwarden From a40e206c082923cef1389cbef2a2e60387d8c1cd Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Sun, 8 Oct 2023 00:37:43 +0200 Subject: [PATCH 06/12] 80 Refactor --- README.md | 5 +++ main.yml | 9 +++--- services/README.md | 1 + services/filebrowser/docker-stack.yml | 2 +- services/homer/assets/config.yml | 10 +++++- services/homer/assets/tools/it-tools.png | Bin 0 -> 26300 bytes services/homer/docker-stack.yml | 4 +-- services/it-tools/.env_it-tools | 2 ++ services/it-tools/docker-stack.yml | 29 ++++++++++++++++++ services/jacket/docker-stack.yml | 2 +- services/jellyfin/docker-stack.yml | 2 +- services/monitoring/docker-stack.yml | 16 +++++----- services/nextcloud/docker-stack.yml | 2 +- services/pihole/docker-stack.yml | 2 +- .../qbittorrent/{config => }/.env_qbittorrent | 2 +- services/qbittorrent/docker-stack.yml | 4 +-- services/radarr/docker-stack.yml | 2 +- services/rest-server/docker-stack.yml | 2 +- services/searxng/docker-stack.yml | 2 +- services/sonarr/docker-stack.yml | 2 +- services/traefik/docker-stack.yml | 12 ++------ .../traefik/{networks.yml => network.yml} | 2 +- services/vaultwarden/docker-stack.yml | 2 +- tasks/deploy-services.yml | 7 +---- vars.yml | 8 +++-- 25 files changed, 83 insertions(+), 48 deletions(-) create mode 100644 services/homer/assets/tools/it-tools.png create mode 100644 services/it-tools/.env_it-tools create mode 100644 services/it-tools/docker-stack.yml rename services/qbittorrent/{config => }/.env_qbittorrent (65%) rename services/traefik/{networks.yml => network.yml} (97%) diff --git a/README.md b/README.md index e46f8f8..3331469 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,11 @@ rest-server
rest-server
(Restic) +
+
+ IT-Tools
IT-Tools +
+
diff --git a/main.yml b/main.yml index 44a5e1e..1b661f8 100644 --- a/main.yml +++ b/main.yml @@ -1,17 +1,18 @@ --- - name: Homeserver Automation - hosts: all + hosts: localhost vars_files: - vars.yml roles: - - veerendra2.prepare_dev_setup + - role: veerendra2.prepare_dev_setup + tags: system tasks: - name: Prepare Pi ansible.builtin.import_tasks: tasks/prepare-pi.yml become: true - tags: prepare-pi + tags: pi - name: Deploy services ansible.builtin.import_tasks: tasks/deploy-services.yml @@ -22,6 +23,6 @@ ansible.builtin.import_tasks: tasks/ufw.yml become: true - - name: Performing smoke tests + - name: Run smoke tests ansible.builtin.import_tasks: tasks/smoke-tests.yml tags: never diff --git a/services/README.md b/services/README.md index 5bceb05..a6e5cdf 100644 --- a/services/README.md +++ b/services/README.md @@ -1 +1,2 @@ # Docker Swarm Services +Update your duckdns sub-domain name in traefik label in all services. For example [./traefik/docker-stack.yml#31](./traefik/docker-stack.yml#31) diff --git a/services/filebrowser/docker-stack.yml b/services/filebrowser/docker-stack.yml index d5f62ac..fa5a894 100644 --- a/services/filebrowser/docker-stack.yml +++ b/services/filebrowser/docker-stack.yml @@ -8,7 +8,7 @@ networks: services: filebrowser: - image: filebrowser/filebrowser:v2.24.1 + image: filebrowser/filebrowser:latest deploy: replicas: 1 placement: diff --git a/services/homer/assets/config.yml b/services/homer/assets/config.yml index 79d8d1a..84cddf6 100644 --- a/services/homer/assets/config.yml +++ b/services/homer/assets/config.yml @@ -135,6 +135,7 @@ services: # subtitle: "Container management UI" # url: "/portainer/" # method: "get" + - name: "Filebrowser" type: "Ping" logo: "assets/tools/filebrowser.png" @@ -162,7 +163,7 @@ services: # url: "/vaultwarden/" # method: "get" - # - name: Search + # - name: Utilities # icon: "" # items: # - name: "SearXNG" @@ -171,3 +172,10 @@ services: # subtitle: "Metasearch engine" # url: "/searxng/" # method: "get" + + # - name: "IT-Tools" + # type: "Ping" + # logo: "assets/tools/it-tools.png" + # subtitle: "Useful tools for developer" + # url: "/it-tools/" + # method: "get" diff --git a/services/homer/assets/tools/it-tools.png b/services/homer/assets/tools/it-tools.png new file mode 100644 index 0000000000000000000000000000000000000000..17df08f5d051dfe65b3e442725f13cecdc28153d GIT binary patch literal 26300 zcmYhj2{@GR7dQTl!H}J@#8|T=yRRj?D2yzLkUd2qOGb9ak|nZb%`OuyLPCvgq)23$ z$`XSpj4k`ly!Z6`zwhCR4uTe(AxJG3 zg1CGOa91?I2edbg4fG*0<*THn;xTwa?`vr54?&22%0F1#6!_xrmshW?_<5 zT6Rc!3qiL;jP!LagMKa(1H*p&*(0y*1VozBj=^rG6>ta!WbRi3J}3^g8#(hySufU%Yv< z!2fmsyP{MB0jtntw>afY5VihWmvX|>z-s35tAE-Po z)}qq6pTS`djZN-#d}mr+IgXsTs8da22XAi2^Ex-Tm#EM+bUYeq^TECFL()kd?OCE) zkVXgz?D5NzXE!r?Ohw^ba8(|R2=TwLw=wOJw634%ZjxJ{zX^GXPPafIAgqQ^b;vdk z=d3?>c{&;iPfA#3?Z~NFwXf;}^39^BLig&TDj1*Sp@_Nn6`Cdo}&% zH3Kl6=l^xTlvFRIKNr=Kv-bSxOu~E1K&ng>3lhpi#f*;`Pkik>Ow=(jYz(qj`CKqs z>%8Yr5JJ%uQiiozSr+ARF3^VON)o3zmf7x^c{>ce(*->XDiUBQn$s~Os)0IO!VxHu@<^d zK|e;>Bgniel|v($8b?@ctWHJDEaO9Ui_~rwq`yA*JuUZ2Npz*|%~< zss)c4N8BsRHAzCo~}DML41J&= z8HuWrg{-%$k^hD+qm2JipN7Dsdu{w%*<@WNiv8$@g=AuaUpYF)0>u;yBreKPtMx(o z0nXoGaYqXD(w3Wv5)(s07N5OIL;gUl>=fC`v{1`E7-ut}%qN5L&BCt%t(*2fd~7o` z+rp^K=`u<*%deavy4UT|;QyP=!+KV_KXSubva{7i zm|)Ysey23L*k*e+OP?|Px`X8V#Ds``3rVBRB%|lQ3DwU}PA6+2YyQ7R_ejH;7GJnF z^Rq0v^+V`%&i-McDCOl>PFGQ9BL{r0p+wmhDX)lAUNO?&SHfnl(^H1~|F^{UQ<roRxP=N!GcDky6!}>U*kmxZoT>qxQMSk^r14@WN<{+uUFYAf zn{#p*{lDMd*gO#~ECDUCIZ|h{sK1>?DFp5evcOInH&W-Bm@nq`n2pqLd^|UapGmDl zr&>fj6PG%xWRt{|KR(h{@wlCo?WYzs!63+>(~7>H;3Yob�l-8UC#6=HcGgmn-8k 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 literal 0 HcmV?d00001 diff --git a/services/homer/docker-stack.yml b/services/homer/docker-stack.yml index bc9cbc6..949e10b 100644 --- a/services/homer/docker-stack.yml +++ b/services/homer/docker-stack.yml @@ -8,7 +8,7 @@ networks: services: homer: - image: b4bz/homer:v23.05.1 + image: b4bz/homer:latest deploy: replicas: 1 placement: @@ -20,8 +20,8 @@ services: labels: - "traefik.enable=true" - "traefik.docker.network=network_public" - - "traefik.http.routers.homer.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/`)" - "traefik.http.routers.homer.tls=true" + - "traefik.http.routers.homer.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/`)" - "traefik.http.services.homer.loadbalancer.server.port=8080" hostname: homer env_file: diff --git a/services/it-tools/.env_it-tools b/services/it-tools/.env_it-tools new file mode 100644 index 0000000..b282701 --- /dev/null +++ b/services/it-tools/.env_it-tools @@ -0,0 +1,2 @@ +#https://github.com/CorentinTh/it-tools/pull/461 +BASE_URL=/it-tools \ No newline at end of file diff --git a/services/it-tools/docker-stack.yml b/services/it-tools/docker-stack.yml new file mode 100644 index 0000000..0d85da6 --- /dev/null +++ b/services/it-tools/docker-stack.yml @@ -0,0 +1,29 @@ +--- +version: '3.8' + +networks: + network_public: + external: true + +services: + it-tools: + image: corentinth/it-tools:latest + deploy: + replicas: 1 + placement: + constraints: [node.role == manager] + restart_policy: + condition: on-failure + delay: 30s + max_attempts: 3 + labels: + - "traefik.enable=true" + - "traefik.docker.network=network_public" + - "traefik.http.routers.it-tools.tls=true" + - "traefik.http.routers.it-tools.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/it-tools`)" + - "traefik.http.services.it-tools.loadbalancer.server.port=80" + hostname: it-tools + env_file: + - .env_it-tools + networks: + - network_public diff --git a/services/jacket/docker-stack.yml b/services/jacket/docker-stack.yml index 1eea633..e30b31c 100644 --- a/services/jacket/docker-stack.yml +++ b/services/jacket/docker-stack.yml @@ -7,7 +7,7 @@ networks: services: jackett: - image: linuxserver/jackett:arm64v8-0.21.568 + image: linuxserver/jackett:arm64v8-latest deploy: replicas: 1 placement: diff --git a/services/jellyfin/docker-stack.yml b/services/jellyfin/docker-stack.yml index 15d1ac6..46963e3 100644 --- a/services/jellyfin/docker-stack.yml +++ b/services/jellyfin/docker-stack.yml @@ -8,7 +8,7 @@ networks: services: jellyfin: - image: jellyfin/jellyfin:10.8.10 + image: jellyfin/jellyfin:10.8.11 deploy: replicas: 1 placement: diff --git a/services/monitoring/docker-stack.yml b/services/monitoring/docker-stack.yml index 52a5d5b..7263a7a 100644 --- a/services/monitoring/docker-stack.yml +++ b/services/monitoring/docker-stack.yml @@ -18,7 +18,7 @@ secrets: services: prometheus: - image: prom/prometheus-linux-arm64:v2.46.0 + image: prom/prometheus-linux-arm64:latest deploy: replicas: 1 placement: @@ -36,7 +36,7 @@ services: hostname: prometheus volumes: - ./prometheus:/etc/prometheus - - /media/disk2/volumes/prometheus:/prometheus + - prometheus:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' @@ -52,7 +52,7 @@ services: - network_monitoring grafana: - image: grafana/grafana:10.0.3 + image: grafana/grafana:latest deploy: replicas: 1 placement: @@ -71,7 +71,7 @@ services: - traefik.http.services.grafana.loadbalancer.server.port=3000 hostname: grafana volumes: - - /media/disk2/volumes/grafana:/var/lib/grafana + - grafana:/var/lib/grafana - ./grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards - ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources env_file: @@ -85,7 +85,7 @@ services: - grafana_admin_password nodeexporter: - image: prom/node-exporter-linux-arm64:v1.6.1 + image: prom/node-exporter-linux-arm64:latest deploy: mode: global restart_policy: @@ -112,7 +112,7 @@ services: # Caution: cadvisor is reletivly CPU hunger. # https://github.com/google/cadvisor/issues/2523 cadvisor: - image: gcr.io/cadvisor/cadvisor-arm64:v0.47.1 + image: gcr.io/cadvisor/cadvisor-arm64:v0.47.2 deploy: mode: global restart_policy: @@ -139,7 +139,7 @@ services: - network_monitoring ping: - image: prom/blackbox-exporter-linux-arm64:v0.24.0 + image: prom/blackbox-exporter-linux-arm64:latest deploy: replicas: 1 placement: @@ -164,7 +164,7 @@ services: - network_monitoring speedtest: - image: ghcr.io/miguelndecarvalho/speedtest-exporter:v3.5.3 + image: ghcr.io/miguelndecarvalho/speedtest-exporter:latest deploy: replicas: 1 placement: diff --git a/services/nextcloud/docker-stack.yml b/services/nextcloud/docker-stack.yml index e10f5a9..bd9ce4b 100644 --- a/services/nextcloud/docker-stack.yml +++ b/services/nextcloud/docker-stack.yml @@ -24,7 +24,7 @@ secrets: services: nextcloud: - image: arm64v8/nextcloud:27.0.1-apache + image: arm64v8/nextcloud:27.1.1-apache deploy: replicas: 1 placement: diff --git a/services/pihole/docker-stack.yml b/services/pihole/docker-stack.yml index afbcef8..b842c4f 100644 --- a/services/pihole/docker-stack.yml +++ b/services/pihole/docker-stack.yml @@ -12,7 +12,7 @@ secrets: services: pihole: - image: pihole/pihole:2023.05.2 + image: pihole/pihole:latest deploy: replicas: 1 placement: diff --git a/services/qbittorrent/config/.env_qbittorrent b/services/qbittorrent/.env_qbittorrent similarity index 65% rename from services/qbittorrent/config/.env_qbittorrent rename to services/qbittorrent/.env_qbittorrent index 42e6b1e..2ff0457 100644 --- a/services/qbittorrent/config/.env_qbittorrent +++ b/services/qbittorrent/.env_qbittorrent @@ -1,4 +1,4 @@ PUID=1000 PGID=1003 TZ=Etc/UTC -WEBUI_PORT=8080 +WEBUI_PORT=8080 \ No newline at end of file diff --git a/services/qbittorrent/docker-stack.yml b/services/qbittorrent/docker-stack.yml index 2d66ec1..20989df 100644 --- a/services/qbittorrent/docker-stack.yml +++ b/services/qbittorrent/docker-stack.yml @@ -39,7 +39,7 @@ services: - net.ipv6.conf.all.disable_ipv6=0 qbittorrent: - image: linuxserver/qbittorrent:arm64v8-4.5.4 + image: linuxserver/qbittorrent:arm64v8-latest deploy: replicas: 1 placement: @@ -65,7 +65,7 @@ services: volumes: - ./config/qBittorrent.conf:/config/qBittorrent/qBittorrent.conf - ./ip-test.sh:/opt/ip-test.sh - - /media/disk2/volumes/qbitorrent:/config + - /media/disk2/volumes/qbittorrent:/config - /media/disk2/downloads:/downloads # healthcheck: # test: ["CMD", "/opt/ip-test.sh"] diff --git a/services/radarr/docker-stack.yml b/services/radarr/docker-stack.yml index 87e77c6..b7a401c 100644 --- a/services/radarr/docker-stack.yml +++ b/services/radarr/docker-stack.yml @@ -7,7 +7,7 @@ networks: services: radarr: - image: linuxserver/radarr:arm64v8-4.6.4 + image: linuxserver/radarr:arm64v8-latest deploy: replicas: 1 placement: diff --git a/services/rest-server/docker-stack.yml b/services/rest-server/docker-stack.yml index bf2e588..e4b8fe2 100644 --- a/services/rest-server/docker-stack.yml +++ b/services/rest-server/docker-stack.yml @@ -12,7 +12,7 @@ secrets: services: rest-server: - image: restic/rest-server:0.12.1 + image: restic/rest-server:latest deploy: replicas: 1 placement: diff --git a/services/searxng/docker-stack.yml b/services/searxng/docker-stack.yml index fa7d6cf..62dd0c6 100644 --- a/services/searxng/docker-stack.yml +++ b/services/searxng/docker-stack.yml @@ -8,7 +8,7 @@ networks: services: searxng: - image: searxng/searxng:2023.7.29-8b4ba204b + image: searxng/searxng:latest deploy: replicas: 1 placement: diff --git a/services/sonarr/docker-stack.yml b/services/sonarr/docker-stack.yml index b3fdbff..0953b43 100644 --- a/services/sonarr/docker-stack.yml +++ b/services/sonarr/docker-stack.yml @@ -7,7 +7,7 @@ networks: services: sonarr: - image: linuxserver/sonarr:arm64v8-3.0.10 + image: linuxserver/sonarr:arm64v8-latest deploy: replicas: 1 placement: diff --git a/services/traefik/docker-stack.yml b/services/traefik/docker-stack.yml index 9c64bf5..1316899 100644 --- a/services/traefik/docker-stack.yml +++ b/services/traefik/docker-stack.yml @@ -7,21 +7,13 @@ networks: network_private: external: true -volumes: - traefik: - driver: local - driver_opts: - o: bind - type: none - device: /media/disk2/volumes/traefik - secrets: duckdns: file: /media/disk2/volumes/secrets/duckdns.txt services: traefik: - image: arm64v8/traefik:v2.10.4 + image: arm64v8/traefik:latest deploy: replicas: 1 placement: @@ -53,7 +45,7 @@ services: mode: host volumes: - /var/run/docker.sock:/var/run/docker.sock - - traefik:/opt + - /media/disk2/volumes/traefik:/opt - ./config:/etc/traefik networks: - network_public diff --git a/services/traefik/networks.yml b/services/traefik/network.yml similarity index 97% rename from services/traefik/networks.yml rename to services/traefik/network.yml index 926af86..1739f66 100644 --- a/services/traefik/networks.yml +++ b/services/traefik/network.yml @@ -1,4 +1,4 @@ -version: 3.8 +version: '3.8' services: networks_scratch: diff --git a/services/vaultwarden/docker-stack.yml b/services/vaultwarden/docker-stack.yml index 29eb4a9..f15157f 100644 --- a/services/vaultwarden/docker-stack.yml +++ b/services/vaultwarden/docker-stack.yml @@ -18,7 +18,7 @@ secrets: services: vaultwarden: - image: vaultwarden/server:1.29.1-alpine + image: vaultwarden/server:latest deploy: replicas: 1 placement: diff --git a/tasks/deploy-services.yml b/tasks/deploy-services.yml index 06373a5..956d725 100644 --- a/tasks/deploy-services.yml +++ b/tasks/deploy-services.yml @@ -1,7 +1,4 @@ --- -# This deploy-services.yml tasks will be replaced with proper GitOps in future -# https://github.com/veerendra2/raspberrypi-homeserver/issues/54 - - name: Create base directory ansible.builtin.file: path: "{{ services_base_dir_location }}" @@ -31,7 +28,7 @@ - name: Create networks community.docker.docker_stack: state: present - name: traefik + name: network compose: - "{{ [services_base_dir_location, 'traefik', 'network.yml'] | path_join }}" @@ -41,6 +38,4 @@ name: "{{ item }}" compose: - "{{ [services_base_dir_location, item, 'docker-stack.yml'] | path_join }}" - env: - DOMAIN: "{{ duckdns_domain }}" with_items: "{{ services }}" diff --git a/vars.yml b/vars.yml index db4b1ae..6bed586 100644 --- a/vars.yml +++ b/vars.yml @@ -1,6 +1,7 @@ --- -# Services to be deployed. Names has to match in services/ directory. +# Services to be deployed. services: + - traefik - databases - filebrowser - homer @@ -9,6 +10,7 @@ services: - nextcloud - rest-server - qbittorrent + # - it-tools # - pihole # - portainer # - radarr @@ -26,6 +28,8 @@ enable_docker_swarm_metrics: true enable_docker_swarm_mode: true docker_swarm_advertise_addr: 192.168.0.120 +run_user: "{{ ansible_env.USER }}" + # Reboot after running tasks in tasks/prepare-pi.yml reboot_after_pi_preparation: true @@ -45,5 +49,3 @@ disable_bluetooth: true # VPN ip to test connection is secure. More info in https://github.com/veerendra2/raspberrypi-homeserver/blob/main/services/torrent/README.md vpn_ip: "" -# DuckDNS domain to generate certificates -duckdns_domain: "" From 776e0c4cfe8cf445a82f0352e48a6f9587c0f77b Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Sun, 8 Oct 2023 17:01:56 +0200 Subject: [PATCH 07/12] 80 Fix lint errors --- .ansible-lint | 9 ++++ .github/FUNDING.yml | 1 - inventory.yml | 19 +++---- main.yml | 10 ++-- services/databases/docker-stack.yml | 12 ++--- services/filebrowser/docker-stack.yml | 1 - .../provisioning/dashboards/dashboard.yml | 3 +- .../provisioning/datasources/datasource.yml | 1 + services/monitoring/prometheus/prometheus.yml | 5 +- services/portainer/docker-stack.yml | 1 - services/rest-server/docker-stack.yml | 3 +- services/searxng/config/settings.yml | 1 + services/searxng/docker-stack.yml | 1 + services/traefik/docker-stack.yml | 3 +- services/traefik/network.yml | 1 + services/vaultwarden/docker-stack.yml | 1 + tasks/deploy-services.yml | 9 ++-- tasks/pigpio.yml | 16 +++--- tasks/pihole.yml | 14 +++--- tasks/prepare-pi.yml | 6 +-- tasks/smoke-tests.yml | 49 ------------------- tasks/ufw.yml | 17 ++++--- vars.yml | 7 ++- 23 files changed, 79 insertions(+), 111 deletions(-) delete mode 100644 .github/FUNDING.yml delete mode 100644 tasks/smoke-tests.yml diff --git a/.ansible-lint b/.ansible-lint index 37ca0f9..1600213 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,2 +1,11 @@ --- verbosity: 1 + +skip_list: + - 'yaml' + - 'role-name' + - 'package-latest' + - 'latest[git]' + - 'no-changed-when' + - 'schema[meta]' + - 'ignore-errors' diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 3c05007..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: veerendra2 diff --git a/inventory.yml b/inventory.yml index 8bbf3da..46a9fb6 100644 --- a/inventory.yml +++ b/inventory.yml @@ -1,11 +1,12 @@ +--- all: - # hosts: - # atom: - # ansible_ssh_port: 22 - # ansible_ssh_host: 192.168.0.120 - # ansible_ssh_user: veerendra - # # ansible_ssh_password: - # extra_hosts: - # - "atom:192.168.0.130" # Wifi Address + hosts: + atom: + ansible_ssh_port: 22 + ansible_ssh_host: 192.168.0.120 + ansible_ssh_user: veerendra + # ansible_ssh_password: + extra_hosts: + - "atom:192.168.0.130" localhost: - ansible_connection: local \ No newline at end of file + ansible_connection: local diff --git a/main.yml b/main.yml index 1b661f8..5d25a58 100644 --- a/main.yml +++ b/main.yml @@ -4,9 +4,9 @@ vars_files: - vars.yml - roles: - - role: veerendra2.prepare_dev_setup - tags: system + # roles: + # - role: veerendra2.prepare_dev_setup + # tags: system tasks: - name: Prepare Pi @@ -22,7 +22,3 @@ - name: Setup firewall rules ansible.builtin.import_tasks: tasks/ufw.yml become: true - - - name: Run smoke tests - ansible.builtin.import_tasks: tasks/smoke-tests.yml - tags: never diff --git a/services/databases/docker-stack.yml b/services/databases/docker-stack.yml index bd144e8..71f62b9 100644 --- a/services/databases/docker-stack.yml +++ b/services/databases/docker-stack.yml @@ -56,12 +56,12 @@ services: labels: - "traefik.enable=false" hostname: redis - command: [ - "sh", "-c", - ' - docker-entrypoint.sh - --requirepass "$$(cat $$REDIS_PASSWORD_FILE)" - ' + command: [ + "sh", "-c", + ' + docker-entrypoint.sh + --requirepass "$$(cat $$REDIS_PASSWORD_FILE)" + ' ] env_file: - .env_redis diff --git a/services/filebrowser/docker-stack.yml b/services/filebrowser/docker-stack.yml index fa5a894..acd9c35 100644 --- a/services/filebrowser/docker-stack.yml +++ b/services/filebrowser/docker-stack.yml @@ -35,4 +35,3 @@ services: - /media/disk1:/srv/disk1 networks: network_public: - diff --git a/services/monitoring/grafana/provisioning/dashboards/dashboard.yml b/services/monitoring/grafana/provisioning/dashboards/dashboard.yml index d83b43c..273961a 100644 --- a/services/monitoring/grafana/provisioning/dashboards/dashboard.yml +++ b/services/monitoring/grafana/provisioning/dashboards/dashboard.yml @@ -1,3 +1,4 @@ +--- apiVersion: 1 providers: @@ -9,4 +10,4 @@ providers: editable: true allowUiUpdates: true options: - path: /etc/grafana/provisioning/dashboards \ No newline at end of file + path: /etc/grafana/provisioning/dashboards diff --git a/services/monitoring/grafana/provisioning/datasources/datasource.yml b/services/monitoring/grafana/provisioning/datasources/datasource.yml index 89a7dca..ab2e71b 100644 --- a/services/monitoring/grafana/provisioning/datasources/datasource.yml +++ b/services/monitoring/grafana/provisioning/datasources/datasource.yml @@ -1,3 +1,4 @@ +--- apiVersion: 1 datasources: diff --git a/services/monitoring/prometheus/prometheus.yml b/services/monitoring/prometheus/prometheus.yml index 717e02b..0f1edab 100644 --- a/services/monitoring/prometheus/prometheus.yml +++ b/services/monitoring/prometheus/prometheus.yml @@ -1,3 +1,4 @@ +--- global: scrape_interval: 15s evaluation_interval: 15s @@ -8,8 +9,8 @@ global: monitor: "docker-host-alpha" # Load and evaluate rules in this file every 'evaluation_interval' seconds. -#rule_files: -# - "alert.rules" +# rule_files: +# - "alert.rules" # A scrape configuration containing exactly one endpoint to scrape. scrape_configs: diff --git a/services/portainer/docker-stack.yml b/services/portainer/docker-stack.yml index e69f8a1..c4d0880 100644 --- a/services/portainer/docker-stack.yml +++ b/services/portainer/docker-stack.yml @@ -42,4 +42,3 @@ services: - network_public secrets: - portainer_admin_password - diff --git a/services/rest-server/docker-stack.yml b/services/rest-server/docker-stack.yml index e4b8fe2..5e38e25 100644 --- a/services/rest-server/docker-stack.yml +++ b/services/rest-server/docker-stack.yml @@ -1,3 +1,4 @@ +--- version: "3.8" networks: @@ -37,4 +38,4 @@ services: - network_public - network_monitoring secrets: - - htpasswd \ No newline at end of file + - htpasswd diff --git a/services/searxng/config/settings.yml b/services/searxng/config/settings.yml index bc2dabb..6af4357 100644 --- a/services/searxng/config/settings.yml +++ b/services/searxng/config/settings.yml @@ -1,3 +1,4 @@ +--- general: # Debug mode, only for development. Is overwritten by ${SEARXNG_DEBUG} debug: false diff --git a/services/searxng/docker-stack.yml b/services/searxng/docker-stack.yml index 62dd0c6..174c7de 100644 --- a/services/searxng/docker-stack.yml +++ b/services/searxng/docker-stack.yml @@ -1,3 +1,4 @@ +--- version: "3.8" networks: diff --git a/services/traefik/docker-stack.yml b/services/traefik/docker-stack.yml index 1316899..63f7ca9 100644 --- a/services/traefik/docker-stack.yml +++ b/services/traefik/docker-stack.yml @@ -1,3 +1,4 @@ +--- # https://dust6765.gitbook.io/raspberrypi-home-server/services/traefik-proxy version: "3.8" @@ -51,4 +52,4 @@ services: - network_public - network_private secrets: - - duckdns \ No newline at end of file + - duckdns diff --git a/services/traefik/network.yml b/services/traefik/network.yml index 1739f66..92f3a9b 100644 --- a/services/traefik/network.yml +++ b/services/traefik/network.yml @@ -1,3 +1,4 @@ +--- version: '3.8' services: diff --git a/services/vaultwarden/docker-stack.yml b/services/vaultwarden/docker-stack.yml index f15157f..4d190c1 100644 --- a/services/vaultwarden/docker-stack.yml +++ b/services/vaultwarden/docker-stack.yml @@ -1,3 +1,4 @@ +--- version: '3.8' networks: diff --git a/tasks/deploy-services.yml b/tasks/deploy-services.yml index 956d725..f737d95 100644 --- a/tasks/deploy-services.yml +++ b/tasks/deploy-services.yml @@ -4,10 +4,11 @@ path: "{{ services_base_dir_location }}" state: directory owner: "{{ run_user }}" - become: yes + mode: '0644' + become: true -# Run pre deploy tasks for services -- include_tasks: pihole.yml +- name: Include pihole tasks + ansible.builtin.include_tasks: pihole.yml when: "'pihole' in services" - name: Create .vpn_ip file for torrent service @@ -15,6 +16,8 @@ dest: services/torrent/.vpn_ip content: | VPN_IP={{ vpn_ip }} + owner: "{{ run_user }}" + mode: '0644' when: "vpn_ip and 'torrent' in services" - name: Synchronize services directories diff --git a/tasks/pigpio.yml b/tasks/pigpio.yml index 70e63f9..94c8c72 100644 --- a/tasks/pigpio.yml +++ b/tasks/pigpio.yml @@ -9,6 +9,8 @@ ansible.builtin.get_url: url: https://github.com/joan2937/pigpio/archive/master.zip dest: "{{ tempdir.path }}" + owner: "{{ run_user }}" + mode: '0440' # TODO need to test! - name: Extract pigpio ansible.builtin.unarchive: @@ -24,7 +26,6 @@ - name: Set systemd unit parameters for pigpiod ansible.builtin.set_fact: - name: pigpiod description: Daemon required to control GPIO pins via pigpio exec_start_cmd: /usr/local/bin/pigpiod exec_kill_cmd: /bin/systemctl kill pigpiod @@ -37,12 +38,13 @@ ansible.builtin.template: src: templates/systemd_unit.service.j2 dest: /lib/systemd/system/pigpiod.service + mode: '0640' - name: Enable and start pigpiod systemd daemon ansible.builtin.systemd: name: pigpiod - enabled: yes - daemon_reload: yes + enabled: true + daemon_reload: true state: started - name: Copy fan.py script @@ -53,7 +55,6 @@ - name: Set systemd unit parameters for fan-py ansible.builtin.set_fact: - name: fan-py description: Daemon required to control fan speed via pigpio exec_start_cmd: /usr/bin/python3 /usr/local/bin/fan.py exec_kill_cmd: /bin/kill -TERM $MAINPID @@ -62,14 +63,15 @@ pre_start_cmd: /bin/sleep 5 service_type: simple -- name: Create fan-py systemd unit +- name: Create fan-py systemd unit file ansible.builtin.template: src: templates/systemd_unit.service.j2 dest: /lib/systemd/system/fan-py.service + mode: '0640' - name: Enable and start fan-py systemd daemon ansible.builtin.systemd: name: fan-py - enabled: yes - daemon_reload: yes + enabled: true + daemon_reload: true state: started diff --git a/tasks/pihole.yml b/tasks/pihole.yml index 37bf925..e2d3635 100644 --- a/tasks/pihole.yml +++ b/tasks/pihole.yml @@ -2,7 +2,7 @@ # https://github.com/pi-hole/docker-pi-hole#installing-on-ubuntu-or-fedora - name: Disable stub resolver in systemd-resolved config - ini_file: + community.general.ini_fil: path: /etc/systemd/resolved.conf section: Resolve option: DNSStubListener @@ -10,24 +10,24 @@ backup: true - name: Create backup /etc/resolv.conf - copy: - remote_src: yes + ansible.builtin.copy`: + remote_src: true src: /etc/resolv.conf dest: /etc/resolv.conf.backup - name: Remove /etc/resolv.conf - file: + ansible.builtin.file: path: /etc/resolv.conf state: absent - name: Create link /etc/resolv.conf - file: + ansible.builtin.file: src: /run/systemd/resolve/resolv.conf dest: /etc/resolv.conf state: link - ignore_errors: yes + ignore_errors: true - name: Restart systemd-resolved - service: + ansible.builtin.service: name: systemd-resolved state: restarted diff --git a/tasks/prepare-pi.yml b/tasks/prepare-pi.yml index f3d72d8..3ea56e8 100644 --- a/tasks/prepare-pi.yml +++ b/tasks/prepare-pi.yml @@ -1,5 +1,6 @@ --- - name: Install fan script + when: install_fan_script block: - name: Check fan-py daemon is loaded ansible.builtin.systemd: @@ -9,21 +10,20 @@ - name: Install pigpio and Pi fan controller ansible.builtin.include_tasks: pigpio.yml when: output.status.LoadState != 'loaded' - when: install_fan_script - name: Power optimization + when: disable_bluetooth block: - name: Stop and disable hciuart and bluetooth deamon ansible.builtin.systemd: name: "{{ item }}" state: stopped - enabled: no + enabled: false with_items: - bluetooth - hciuart - name: Disable HDMI Output ansible.builtin.command: /usr/bin/tvservice -o - when: disable_bluetooth|bool == true - name: Configure disk mounts in /etc/fstab ansible.posix.mount: diff --git a/tasks/smoke-tests.yml b/tasks/smoke-tests.yml deleted file mode 100644 index 1fda3d1..0000000 --- a/tasks/smoke-tests.yml +++ /dev/null @@ -1,49 +0,0 @@ ---- -- name: Fetch docker swarm info - community.docker.docker_swarm_info: - nodes: yes - services: yes - ignore_errors: yes - register: swarm_info - -- ansible.builtin.debug: - msg: | - ***************** DOCKER SWARM INFO ***************** - can_talk_to_docker: {{ swarm_info.can_talk_to_docker }} - docker_swarm_active: {{ swarm_info.docker_swarm_active }} - docker_swarm_manager: {{ swarm_info.docker_swarm_manager }} - failed: {{ swarm_info.failed }} - ***************** DOCKER SWARM NODES ***************** - {% for node in swarm_info.nodes %} - Node name: {{ node.Hostname }} - Availability: {{ node.Availability }} - ManagerStatus: {{ node.ManagerStatus }} - Status: {{ node.Status }} - {% endfor %} - -- name: Running HTTP GET - ansible.builtin.get_url: - url: "https://192.168.0.120/{{ item }}/" - dest: /tmp/value - validate_certs: no - register: output - ignore_errors: yes - with_items: - - "dashboard" - - "filebrowser" - - "portainer" - - "admin" - - "grafana" - - "prometheus" - - "jellyfin" - - "nextcloud" - loop_control: - label: "{{ item }}" - -- ansible.builtin.debug: - msg: | - {{ "{:<35} {}".format('URL', 'HTTP RESPONCE CODE') }} - - {% for item in output.results %} - {{ "{:<40} {}".format(item.url, item.status_code) }} - {% endfor %} diff --git a/tasks/ufw.yml b/tasks/ufw.yml index 6ca9058..90eb738 100644 --- a/tasks/ufw.yml +++ b/tasks/ufw.yml @@ -1,5 +1,6 @@ --- -- set_fact: +- name: Set facts + ansible.legacy.set_fact: external_iface_list: - eth0 - wlan0 @@ -19,7 +20,7 @@ - name: Append custom rules in /etc/ufw/after.rules ansible.builtin.blockinfile: dest: /etc/ufw/after.rules - block: "{{ lookup('template', 'templates/override_ufw_rules.j2' ) }}" + block: "{{ lookup('template', 'templates/override_ufw_rules.j2') }}" marker: "#{mark} ANSIBLE MANAGED BLOCK" - name: Set DEFAULT_FORWARD_POLICY=DROP in /etc/default/ufw @@ -27,16 +28,16 @@ path: /etc/default/ufw regexp: '^DEFAULT_FORWARD_POLICY(.*)$' line: 'DEFAULT_FORWARD_POLICY="DROP"' - backup: yes - backrefs: yes + backup: true + backrefs: true - name: Set IPV6=no in /etc/default/ufw ansible.builtin.lineinfile: path: /etc/default/ufw regexp: '^IPV6=(.*)$' line: 'IPV6=no' - backup: yes - backrefs: yes + backup: true + backrefs: true - name: Allow selected tcp ports community.general.ufw: @@ -46,12 +47,12 @@ with_items: "{{ allow_tcp_ports }}" - name: Allow selected udp ports - ufw: + community.general.ufw: rule: allow port: "{{ item }}" proto: udp with_items: "{{ allow_udp_ports }}" - name: Enable ufw - ufw: + community.general.ufw: state: enabled diff --git a/vars.yml b/vars.yml index 6bed586..67e8076 100644 --- a/vars.yml +++ b/vars.yml @@ -38,9 +38,9 @@ install_fan_script: true # Mount partions configuration in /etc/fstab disk_mount_dirs: - # [DISK_PARTITION]: [MOUNT DIRECTORY] - # /dev/sda1: /media/disk1 # Backup disk - /dev/sdb1: /media/disk2 # Main disk for nextcloud, filebrowser, jellyfin and postgres +# [DISK_PARTITION]: [MOUNT DIRECTORY] + - /dev/sdb1: /media/disk2 # Main disk for nextcloud, filebrowser, jellyfin and postgres +# - /dev/sda1: /media/disk1 # Backup disk # Pi power optimization setttings disable_hdmi: true @@ -48,4 +48,3 @@ disable_bluetooth: true # VPN ip to test connection is secure. More info in https://github.com/veerendra2/raspberrypi-homeserver/blob/main/services/torrent/README.md vpn_ip: "" - From df1fae8e14546a33585593d124b764a54ebb827a Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Sun, 8 Oct 2023 21:00:00 +0200 Subject: [PATCH 08/12] 80 Test ansible make module for pigpio --- README.md | 17 +++++++++-------- tasks/pigpio.yml | 24 +++++++++++++----------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 3331469..e0548fe 100644 --- a/README.md +++ b/README.md @@ -212,8 +212,8 @@ $ cd raspberrypi-homeserver $ ansible-playbook main.yml ``` ### NOTE -* The setup created to deploy all services on single node docker swarm cluster. If you want to use this setup on multi node swarm cluster, there are some additional tweaks required like - * Change plancement +* This setup is created to deploy all services on single node docker swarm cluster. If you want to use this setup on multi node swarm cluster, there are some additional tweaks required like + * Change placement ```yaml ... deploy: @@ -222,12 +222,13 @@ $ ansible-playbook main.yml constraints: [node.role == manager] ... ``` -* Currently I'm using duckdns sub-domain. Refer my [blog post](https://veerendra2.github.io/traefik-https) to get more info. +* Currently I'm using duckdns sub-domain (Refer example -> [services/traefik/docker-stack.yml#32](./services/traefik/docker-stack.yml#32)). Refer my [blog post](https://veerendra2.medium.com/traefik-https-config-with-duckdns-for-local-homeserver-c55db9971683) to get more info. +* Update docker volume mount paths. ## Related Blogs -* [Portainer vs Yacht](https://veerendra2.github.io/portainer-vs-yacht) -* [Pi-hole with DHCP Relay in Docker](https://veerendra2.github.io/pihole-dhcp-relay) -* [Wireguard VPN and BitTorrent on Docker Swarm (Part 1)](https://veerendra2.github.io/wireguard-qbittorrent-docker-swarm-1) -* [Wireguard VPN and BitTorrent on Docker Swarm (Part 2)](https://veerendra2.github.io/wireguard-qbittorrent-docker-swarm-2) -* [Traefik HTTPS Config with DuckDNS for Local Homeserver](https://veerendra2.github.io/traefik-https) +* [Portainer vs Yacht](https://veerendra2.medium.com/portainer-vs-yacht-316405b9e867) +* [Pi-hole with DHCP Relay in Docker](https://veerendra2.medium.com/pi-hole-with-dhcp-relay-in-docker-cef397922e5a) +* [Wireguard VPN and BitTorrent on Docker Swarm (Part 1)](https://veerendra2.medium.com/wireguard-vpn-and-bittorrent-on-docker-swarm-part-1-1100b4115cc0) +* [Wireguard VPN and BitTorrent on Docker Swarm (Part 2)](https://veerendra2.medium.com/wireguard-vpn-and-bittorrent-on-docker-swarm-part-2-b92a251ba873) +* [Traefik HTTPS Config with DuckDNS for Local Homeserver](https://veerendra2.medium.com/traefik-https-config-with-duckdns-for-local-homeserver-c55db9971683) * [How to Deploy rest-server(Restic) on Docker Swarm Behind Traefik Reverse Proxy](https://dev.to/veerendra2/how-to-deploy-rest-serverrestic-on-docker-swarm-behind-traefik-reverse-proxy-4a8h) diff --git a/tasks/pigpio.yml b/tasks/pigpio.yml index 94c8c72..1d4cefd 100644 --- a/tasks/pigpio.yml +++ b/tasks/pigpio.yml @@ -11,18 +11,20 @@ dest: "{{ tempdir.path }}" owner: "{{ run_user }}" mode: '0440' -# TODO need to test! -- name: Extract pigpio - ansible.builtin.unarchive: - src: "{{ tempdir.path }}/master.zip" - dest: "{{ tempdir.path }}" -- name: Build and install pigpio - community.general.make: - chdir: "{{ tempdir.path }}" - target: install - params: - NUM_THREADS: 2 + - name: Extract pigpio + ansible.builtin.unarchive: + src: "{{ tempdir.path }}/pigpio-master.zip" + dest: "{{ tempdir.path }}" + remote_src: true + + - name: Build and install pigpio + community.general.make: + chdir: "{{ tempdir.path }}/pigpio-master" + target: install + params: + NUM_THREADS: 2 + become: true - name: Set systemd unit parameters for pigpiod ansible.builtin.set_fact: From 12983cfd7bb15fb576a6a5a11dc70d1c5fafb422 Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Sun, 8 Oct 2023 21:02:05 +0200 Subject: [PATCH 09/12] 80 Fix yaml indentation --- tasks/pigpio.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tasks/pigpio.yml b/tasks/pigpio.yml index 1d4cefd..da02ee4 100644 --- a/tasks/pigpio.yml +++ b/tasks/pigpio.yml @@ -12,19 +12,19 @@ owner: "{{ run_user }}" mode: '0440' - - name: Extract pigpio - ansible.builtin.unarchive: - src: "{{ tempdir.path }}/pigpio-master.zip" - dest: "{{ tempdir.path }}" - remote_src: true +- name: Extract pigpio + ansible.builtin.unarchive: + src: "{{ tempdir.path }}/pigpio-master.zip" + dest: "{{ tempdir.path }}" + remote_src: true - - name: Build and install pigpio - community.general.make: - chdir: "{{ tempdir.path }}/pigpio-master" - target: install - params: - NUM_THREADS: 2 - become: true +- name: Build and install pigpio + community.general.make: + chdir: "{{ tempdir.path }}/pigpio-master" + target: install + params: + NUM_THREADS: 2 + become: true - name: Set systemd unit parameters for pigpiod ansible.builtin.set_fact: From 10ac2942795aaabb49c009d9c348e631e92356a4 Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Sun, 8 Oct 2023 21:14:03 +0200 Subject: [PATCH 10/12] 80 Add ansible.posix --- requirements.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.yml b/requirements.yml index 9fd4476..1795e26 100644 --- a/requirements.yml +++ b/requirements.yml @@ -1,3 +1,4 @@ --- roles: - name: veerendra2.prepare_dev_setup + - name: ansible.posix From c8910ca69f79ed2dce406507f4e2052631a7b252 Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Sun, 8 Oct 2023 21:23:34 +0200 Subject: [PATCH 11/12] 80 Fix ansible lints --- requirements.yml | 2 ++ tasks/pihole.yml | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/requirements.yml b/requirements.yml index 1795e26..b142452 100644 --- a/requirements.yml +++ b/requirements.yml @@ -1,4 +1,6 @@ --- roles: - name: veerendra2.prepare_dev_setup +collections: - name: ansible.posix + - name: community.general diff --git a/tasks/pihole.yml b/tasks/pihole.yml index e2d3635..13c82a5 100644 --- a/tasks/pihole.yml +++ b/tasks/pihole.yml @@ -10,10 +10,11 @@ backup: true - name: Create backup /etc/resolv.conf - ansible.builtin.copy`: + ansible.builtin.copy: remote_src: true src: /etc/resolv.conf dest: /etc/resolv.conf.backup + mode: '0644' - name: Remove /etc/resolv.conf ansible.builtin.file: From bbbe855854dd693939b3f9dfec09f04c2f5995c4 Mon Sep 17 00:00:00 2001 From: veerendra2 Date: Sun, 8 Oct 2023 21:27:35 +0200 Subject: [PATCH 12/12] 80 community.docker collection --- requirements.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.yml b/requirements.yml index b142452..28b5069 100644 --- a/requirements.yml +++ b/requirements.yml @@ -4,3 +4,4 @@ roles: collections: - name: ansible.posix - name: community.general + - name: community.docker