diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..1600213 --- /dev/null +++ b/.ansible-lint @@ -0,0 +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/.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 fced169..e0548fe 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 +# Raspberry Pi Homeserver +

-A collection of applications and tools to make awesome Raspberry Pi homerserver +A collection of self-host docker swarm stacks

@@ -106,6 +107,11 @@ rest-server
rest-server
(Restic) +
+
+ IT-Tools
IT-Tools +
+
@@ -192,10 +198,10 @@ ![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 +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 @@ -206,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: @@ -216,12 +222,13 @@ $ 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 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 -* 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.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/inventory.yml b/inventory.yml index be2c756..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: + # ansible_ssh_password: extra_hosts: - - "atom:192.168.0.130" # Wifi Address + - "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 0c98f0f..5d25a58 100644 --- a/main.yml +++ b/main.yml @@ -1,38 +1,24 @@ -# Author: Veerendra K -# Description: An Ansible playbook to make awesome Raspberry Pi homeserver - -- name: Raspberry Pi Homeserver +--- +- name: Homeserver Automation hosts: localhost - gather_facts: yes 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: + # - role: veerendra2.prepare_dev_setup + # tags: system tasks: - name: Prepare Pi - import_tasks: tasks/prepare-pi.yml - tags: prepare-pi + ansible.builtin.import_tasks: tasks/prepare-pi.yml + become: true + tags: 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 - - - name: Performing smoke tests - import_tasks: tasks/smoke-tests.yml - tags: never + ansible.builtin.import_tasks: tasks/ufw.yml + become: true diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000..28b5069 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,7 @@ +--- +roles: + - name: veerendra2.prepare_dev_setup +collections: + - name: ansible.posix + - name: community.general + - name: community.docker diff --git a/services/README.md b/services/README.md index 46d5a11..a6e5cdf 100644 --- a/services/README.md +++ b/services/README.md @@ -1,7 +1,2 @@ # 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 +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/databases/docker-stack.yml b/services/databases/docker-stack.yml index 98742c1..71f62b9 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 @@ -59,17 +56,17 @@ 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 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..acd9c35 100644 --- a/services/filebrowser/docker-stack.yml +++ b/services/filebrowser/docker-stack.yml @@ -1,17 +1,14 @@ --- # 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 + image: filebrowser/filebrowser:latest deploy: replicas: 1 placement: @@ -24,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 @@ -32,10 +29,9 @@ 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/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 0000000..17df08f Binary files /dev/null and b/services/homer/assets/tools/it-tools.png differ diff --git a/services/homer/docker-stack.yml b/services/homer/docker-stack.yml index 5c8388f..949e10b 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: @@ -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(`${DOMAIN}`) && 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/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/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/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 53% rename from services/torrent/docker-stack-jackett.yml rename to services/jacket/docker-stack.yml index d8fe1dc..e30b31c 100644 --- a/services/torrent/docker-stack-jackett.yml +++ b/services/jacket/docker-stack.yml @@ -1,22 +1,13 @@ --- -# 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 + image: linuxserver/jackett:arm64v8-latest deploy: replicas: 1 placement: @@ -29,16 +20,14 @@ 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: - - ./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 + - /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..46963e3 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: @@ -12,7 +8,7 @@ networks: services: jellyfin: - image: jellyfin/jellyfin:10.8.10 + image: jellyfin/jellyfin:10.8.11 deploy: replicas: 1 placement: @@ -25,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: @@ -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..7263a7a 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: @@ -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: @@ -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: @@ -52,7 +52,7 @@ services: - network_monitoring grafana: - image: grafana/grafana:10.0.3 + image: grafana/grafana:latest deploy: replicas: 1 placement: @@ -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 @@ -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/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/nextcloud/docker-stack.yml b/services/nextcloud/docker-stack.yml index 3a821fc..bd9ce4b 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: @@ -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: @@ -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 b5f823d..b842c4f 100644 --- a/services/pihole/docker-stack.yml +++ b/services/pihole/docker-stack.yml @@ -6,16 +6,13 @@ networks: network_public: external: true -volumes: - pihole: - secrets: pihole_admin_password: file: ./secrets/pihole_admin_password.txt services: pihole: - image: pihole/pihole:2023.05.2 + image: pihole/pihole:latest deploy: replicas: 1 placement: @@ -27,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 @@ -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..c4d0880 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 @@ -28,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 @@ -41,9 +37,8 @@ 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: - portainer_admin_password - diff --git a/services/torrent/qbittorrent/.env_qbittorrent b/services/qbittorrent/.env_qbittorrent similarity index 65% rename from services/torrent/qbittorrent/.env_qbittorrent rename to services/qbittorrent/.env_qbittorrent index 42e6b1e..2ff0457 100644 --- a/services/torrent/qbittorrent/.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/torrent/wireguard/.env_wireguard b/services/qbittorrent/.env_wireguard similarity index 100% rename from services/torrent/wireguard/.env_wireguard rename to services/qbittorrent/.env_wireguard 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 97% rename from services/torrent/README.md rename to services/qbittorrent/README.md index 4994da3..efa2f13 100644 --- a/services/torrent/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/torrent/qbittorrent/qBittorrent.conf b/services/qbittorrent/config/qBittorrent.conf similarity index 100% rename from services/torrent/qbittorrent/qBittorrent.conf rename to services/qbittorrent/config/qBittorrent.conf diff --git a/services/torrent/wireguard/dante-server/danted.conf b/services/qbittorrent/dante-server/danted.conf similarity index 100% rename from services/torrent/wireguard/dante-server/danted.conf rename to services/qbittorrent/dante-server/danted.conf diff --git a/services/torrent/wireguard/dante-server/install.sh b/services/qbittorrent/dante-server/install.sh similarity index 100% rename from services/torrent/wireguard/dante-server/install.sh rename to services/qbittorrent/dante-server/install.sh diff --git a/services/torrent/wireguard/dante-server/run.sh b/services/qbittorrent/dante-server/run.sh similarity index 100% rename from services/torrent/wireguard/dante-server/run.sh rename to services/qbittorrent/dante-server/run.sh diff --git a/services/torrent/docker-stack-qbittorrent.yml b/services/qbittorrent/docker-stack.yml similarity index 68% rename from services/torrent/docker-stack-qbittorrent.yml rename to services/qbittorrent/docker-stack.yml index 21df49f..20989df 100644 --- a/services/torrent/docker-stack-qbittorrent.yml +++ b/services/qbittorrent/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: @@ -8,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 @@ -31,7 +22,7 @@ services: - traefik.enable=false hostname: wireguard env_file: - - ./wireguard/.env_wireguard + - .env_wireguard networks: - network_public - network_private @@ -39,16 +30,16 @@ 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 qbittorrent: - image: linuxserver/qbittorrent:arm64v8-4.5.4 + image: linuxserver/qbittorrent:arm64v8-latest deploy: replicas: 1 placement: @@ -61,27 +52,23 @@ 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 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/qbittorrent:/config - /media/disk2/downloads:/downloads # healthcheck: # test: ["CMD", "/opt/ip-test.sh"] # interval: 2m # timeout: 10s # retries: 3 - - - - diff --git a/services/torrent/ip-test.sh b/services/qbittorrent/ip-test.sh similarity index 73% rename from services/torrent/ip-test.sh rename to services/qbittorrent/ip-test.sh index c70864c..e4d7117 100755 --- a/services/torrent/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/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/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/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/radarr/docker-stack.yml b/services/radarr/docker-stack.yml new file mode 100644 index 0000000..b7a401c --- /dev/null +++ b/services/radarr/docker-stack.yml @@ -0,0 +1,33 @@ +--- +version: 3.8 + +networks: + network_private: + external: true + +services: + radarr: + image: linuxserver/radarr:arm64v8-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_private + - traefik.http.routers.radarr.tls=true + - traefik.http.routers.radarr.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/radarr`) + - traefik.http.services.radarr.loadbalancer.server.port=7878 + hostname: radarr + env_file: + - .env_radarr + networks: + - network_private + volumes: + - ./config/config.xml:/config/config.xml + - /media/disk2/volumes/radarr:/config + - /media/disk2/downloads:/downloads diff --git a/services/rest-server/docker-stack.yml b/services/rest-server/docker-stack.yml index 0197428..5e38e25 100644 --- a/services/rest-server/docker-stack.yml +++ b/services/rest-server/docker-stack.yml @@ -1,3 +1,4 @@ +--- version: "3.8" networks: @@ -12,7 +13,7 @@ secrets: services: rest-server: - image: restic/rest-server:0.12.1 + image: restic/rest-server:latest deploy: replicas: 1 placement: @@ -25,7 +26,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 @@ -37,4 +38,4 @@ services: - network_public - network_monitoring secrets: - - htpasswd \ No newline at end of file + - htpasswd diff --git a/services/searxng/searxng/settings.yml b/services/searxng/config/settings.yml similarity index 99% rename from services/searxng/searxng/settings.yml rename to services/searxng/config/settings.yml index bc2dabb..6af4357 100644 --- a/services/searxng/searxng/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/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..174c7de 100644 --- a/services/searxng/docker-stack.yml +++ b/services/searxng/docker-stack.yml @@ -1,3 +1,4 @@ +--- version: "3.8" networks: @@ -8,7 +9,7 @@ networks: services: searxng: - image: searxng/searxng:2023.7.29-8b4ba204b + image: searxng/searxng:latest deploy: replicas: 1 placement: @@ -21,13 +22,13 @@ 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: - .env_searxng volumes: - - ./searxng:/etc/searxng:rw + - ./config:/etc/searxng:rw networks: - network_public - network_databases 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/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/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/sonarr/docker-stack.yml b/services/sonarr/docker-stack.yml new file mode 100644 index 0000000..0953b43 --- /dev/null +++ b/services/sonarr/docker-stack.yml @@ -0,0 +1,33 @@ +--- +version: '3.8' + +networks: + network_private: + external: true + +services: + sonarr: + image: linuxserver/sonarr:arm64v8-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_private + - traefik.http.routers.sonarr.tls=true + - traefik.http.routers.sonarr.rule=Host(`veeru.duckdns.org`) && PathPrefix(`/sonarr`) + - traefik.http.services.sonarr.loadbalancer.server.port=8989 + hostname: sonarr + env_file: + - .env_sonarr + networks: + - network_private + volumes: + - ./config/config.xml:/config/config.xml + - /media/disk2/volumes/sonarr:/config + - /media/disk2/downloads:/downloads diff --git a/services/torrent/docker-stack-radarr.yml b/services/torrent/docker-stack-radarr.yml deleted file mode 100644 index 353b7a0..0000000 --- a/services/torrent/docker-stack-radarr.yml +++ /dev/null @@ -1,49 +0,0 @@ ---- -# https://dust6765.gitbook.io/raspberrypi-home-server/services/torrent-stack -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 - 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_private - - traefik.http.routers.radarr.tls=true - - traefik.http.routers.radarr.rule=Host(`${DOMAIN}`) && PathPrefix(`/radarr`) - - traefik.http.services.radarr.loadbalancer.server.port=7878 - hostname: radarr - env_file: - - ./radarr/.env_radarr - - .vpn_ip - networks: - - network_private - volumes: - - radarr:/config - - ./radarr/config.xml:/config/config.xml - - ./ip-test.sh:/opt/ip-test.sh - - /media/disk2/downloads:/downloads - # healthcheck: - # test: ["CMD", "/opt/ip-test.sh"] - # interval: 2m - # timeout: 10s - # retries: 3 diff --git a/services/torrent/docker-stack-sonarr.yml b/services/torrent/docker-stack-sonarr.yml deleted file mode 100644 index acf196d..0000000 --- a/services/torrent/docker-stack-sonarr.yml +++ /dev/null @@ -1,49 +0,0 @@ ---- -# https://dust6765.gitbook.io/raspberrypi-home-server/services/torrent-stack -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 - 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_private - - traefik.http.routers.sonarr.tls=true - - traefik.http.routers.sonarr.rule=Host(`${DOMAIN}`) && PathPrefix(`/sonarr`) - - traefik.http.services.sonarr.loadbalancer.server.port=8989 - hostname: sonarr - env_file: - - ./sonarr/.env_sonarr - - .vpn_ip - networks: - - network_private - volumes: - - sonarr:/config - - ./sonarr/config.xml:/config/config.xml - - ./ip-test.sh:/opt/ip-test.sh - - /media/disk2/downloads:/downloads - # healthcheck: - # test: ["CMD", "/opt/ip-test.sh"] - # interval: 2m - # timeout: 10s - # retries: 3 diff --git a/services/traefik/docker-stack.yml b/services/traefik/docker-stack.yml index ed07779..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" @@ -7,21 +8,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: @@ -36,7 +29,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 @@ -53,10 +46,10 @@ 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 - network_private secrets: - - duckdns \ No newline at end of file + - duckdns 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 e8c6e91..92f3a9b 100644 --- a/services/traefik/networks.yml +++ b/services/traefik/network.yml @@ -1,4 +1,5 @@ -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..4d190c1 100644 --- a/services/vaultwarden/docker-stack.yml +++ b/services/vaultwarden/docker-stack.yml @@ -1,4 +1,5 @@ -version: "3.8" +--- +version: '3.8' networks: network_public: @@ -18,7 +19,7 @@ secrets: services: vaultwarden: - image: vaultwarden/server:1.29.1-alpine + image: vaultwarden/server:latest deploy: replicas: 1 placement: @@ -31,19 +32,19 @@ 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 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/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..f737d95 100644 --- a/tasks/deploy-services.yml +++ b/tasks/deploy-services.yml @@ -1,27 +1,27 @@ --- -# 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 - file: + ansible.builtin.file: 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 - copy: + ansible.builtin.copy: 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 - synchronize: + ansible.posix.synchronize: src: "services/" dest: "{{ services_base_dir_location }}" delete: false @@ -29,19 +29,16 @@ perms: false - name: Create networks - docker_stack: + community.docker.docker_stack: state: present - name: traefik + name: network compose: - "{{ [services_base_dir_location, 'traefik', 'network.yml'] | path_join }}" - when: "'traefik' in services" - name: Deploy service stacks - docker_stack: + community.docker.docker_stack: state: present name: "{{ item }}" compose: - "{{ [services_base_dir_location, item, 'docker-stack.yml'] | path_join }}" - env: - DOMAIN: "{{ duckdns_domain }}" with_items: "{{ services }}" 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..da02ee4 100644 --- a/tasks/pigpio.yml +++ b/tasks/pigpio.yml @@ -1,28 +1,33 @@ --- - 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 }}" + owner: "{{ run_user }}" + mode: '0440' -- name: Run make and make install pigpio - shell: | - unzip pigpio-master.zip - cd pigpio-master - sudo make - sudo make install - args: - chdir: "{{ tempdir.path }}" - become: yes +- 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 - set_fact: - name: pigpiod + ansible.builtin.set_fact: description: Daemon required to control GPIO pins via pigpio exec_start_cmd: /usr/local/bin/pigpiod exec_kill_cmd: /bin/systemctl kill pigpiod @@ -32,29 +37,26 @@ 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 + mode: '0640' - name: Enable and start pigpiod systemd daemon - systemd: + ansible.builtin.systemd: name: pigpiod - enabled: yes - daemon_reload: yes + enabled: true + daemon_reload: true 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: - name: fan-py + ansible.builtin.set_fact: 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 @@ -63,16 +65,15 @@ pre_start_cmd: /bin/sleep 5 service_type: simple -- name: Create fan-py systemd unit - template: +- name: Create fan-py systemd unit file + ansible.builtin.template: src: templates/systemd_unit.service.j2 dest: /lib/systemd/system/fan-py.service - become: yes + mode: '0640' - name: Enable and start fan-py systemd daemon - systemd: + ansible.builtin.systemd: name: fan-py - enabled: yes - daemon_reload: yes + enabled: true + daemon_reload: true state: started - become: yes diff --git a/tasks/pihole.yml b/tasks/pihole.yml index ac3351e..13c82a5 100644 --- a/tasks/pihole.yml +++ b/tasks/pihole.yml @@ -1,35 +1,34 @@ --- # 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 + community.general.ini_fil: + 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 + ansible.builtin.copy: + remote_src: true + src: /etc/resolv.conf + dest: /etc/resolv.conf.backup + mode: '0644' - - 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 + ansible.builtin.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 + ansible.builtin.file: + src: /run/systemd/resolve/resolv.conf + dest: /etc/resolv.conf + state: link + ignore_errors: true + +- name: Restart systemd-resolved + ansible.builtin.service: + name: systemd-resolved + state: restarted diff --git a/tasks/prepare-pi.yml b/tasks/prepare-pi.yml index 466815e..3ea56e8 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 + when: 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' + +- name: Power optimization + when: disable_bluetooth + block: + - name: Stop and disable hciuart and bluetooth deamon + ansible.builtin.systemd: + name: "{{ item }}" + state: stopped + enabled: false + with_items: + - bluetooth + - hciuart + - name: Disable HDMI Output + ansible.builtin.command: /usr/bin/tvservice -o - 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 deleted file mode 100644 index 17c66d5..0000000 --- a/tasks/smoke-tests.yml +++ /dev/null @@ -1,49 +0,0 @@ ---- - - name: Fetch docker swarm info - 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 %} - - - 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 }}" - - - 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 995f644..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 @@ -15,45 +16,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: true + backrefs: true - - 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: true + backrefs: true - - 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 + community.general.ufw: + rule: allow + port: "{{ item }}" + proto: udp + with_items: "{{ allow_udp_ports }}" - - name: Enable ufw - ufw: - state: enabled - become: yes +- name: Enable ufw + community.general.ufw: + state: enabled diff --git a/vars.yml b/vars.yml index 4e85def..67e8076 100644 --- a/vars.yml +++ b/vars.yml @@ -1,82 +1,26 @@ --- -# Services to be deployed. Names has to match in services/ directory. +# Services to be deployed. services: + - traefik - databases - filebrowser - homer - jellyfin - monitoring - nextcloud + - rest-server + - qbittorrent + # - it-tools # - pihole - - portainer - - traefik - - torrent + # - 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/ -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,24 +28,19 @@ 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/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 @@ -109,6 +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: "" - -# DuckDNS domain to generate certificates -duckdns_domain: ""