diff options
Diffstat (limited to 'ansible')
28 files changed, 1049 insertions, 0 deletions
diff --git a/ansible/README.md b/ansible/README.md new file mode 100644 index 0000000..f693916 --- /dev/null +++ b/ansible/README.md @@ -0,0 +1,82 @@ +This part of the repo is responsible for provisioning our +home-lab services using Ansible on top of the infrastructure already +created via Terraform. + +The basic pattern is to confiure the service, and then add the upstream host +to our reverse proxy (Caddy) configuration. + + + +# TODOs (in-progress) +1. reverse-proxy init +1. minio user,bucket init +1. static sites using minio bucket + +# Done +1. Adding service to reverse-proxy (Caddy) via api +1. Media Downloader with Transmission, and `*arr` services +1. Plex +1. Password Manager +1. Nextcloud +1. Metrics monitoring + +--- + +# Pre-reqs +* `pip`3 - `sudo apt install python3 python3-pip` +* `ansible` - `pip install --user ansible` + +# Execution +1. (First Time Only) Fork this repo, if you haven't already. +1. (FTO) Make sure that your [`hosts`](./hosts) have been created in the [Terraform](../terraform) section. +1. (FTO) Edit `group_vars/all/vault.example` to your liking. +```bash +echo "YourSecretPassword" > vaultkey +ansible-vault encrypt --output group_vars/all/vault --encrypt-vault-id vaultkey group_vars/all/vault.example +git checkout group_vars/all/vault.example +``` +1. View/edit your encrypted vault: +```bash +ansible-vault view/edit --vault-id vaultkey group_vars/all/vault +``` +1. (FTO) Run the `init.yaml` playbook to install a service +```bash +ansible-playbook -u youruser -i hosts --vault-id vaultkey playbooks/init.yaml --tags=[app name] +``` +1. Use another playbook to modify a service (not yet implemented but planned) +```bash +ansible-playbook -u youruser -i hosts --vault-id vaultkey playbooks/... --tags=[...] +``` + +# Ansible Roles +You can think of each Role being an "app". + +Each Role has a `setup.yaml` task file responsible for installing the app. +It may or may not have other task files depending on what other functionality this Role +supports for this app. + +The `main.yaml` file in the Role determines the flow logic for which task files +are getting run based on Tags for other functionalities (see Tags section below). + + +# Artifacts +The directory `playbooks/artifacts/` is a place where we save the output for some of the roles. + +This not only serves the purpose to tracking important state info for our configurations, +but it also allows us to use some of this info in other parts of Ansible for cleaner automation. + +> Never commit this dir to git. It contains sensitive info! Its already configured to +be ignored by git. + + +# Ansible Tags +Setting up the app is normally done using the Role's name as the tag, +i.e. `--tags <role name>`. + +Any subsequent tasks required beyond setting up the app, will have a different +tag associated for those tasks (along with a different playbook to trigger them). +For example, the MinIO Role will support adding a new user+bucket under the tag `add_minio_user`: + +```bash +ansible-playbook ... playbooks/add_user.yaml --tags add_minio_user +``` diff --git a/ansible/ansible-lint.yaml b/ansible/ansible-lint.yaml new file mode 100644 index 0000000..ce3d0bd --- /dev/null +++ b/ansible/ansible-lint.yaml @@ -0,0 +1,116 @@ +--- +profile: null # min, basic, moderate,safety, shared, production + +# Allows dumping of results in SARIF format +# sarif_file: result.sarif + +# exclude_paths included in this file are parsed relative to this file's location +# and not relative to the CWD of execution. CLI arguments passed to the --exclude +# option are parsed relative to the CWD of execution. +exclude_paths: + - .cache/ # implicit unless exclude_paths is defined in config + - test/fixtures/formatting-before/ + - test/fixtures/formatting-prettier/ +# parseable: true +# quiet: true +# strict: true +# verbosity: 1 + +# Mock modules or roles in order to pass ansible-playbook --syntax-check +mock_modules: + - zuul_return + # note the foo.bar is invalid as being neither a module or a collection + - fake_namespace.fake_collection.fake_module + - fake_namespace.fake_collection.fake_module.fake_submodule +mock_roles: + - mocked_role + - author.role_name # old standalone galaxy role + - fake_namespace.fake_collection.fake_role # role within a collection + +# Enforce variable names to follow pattern below, in addition to Ansible own +# requirements, like avoiding python identifiers. To disable add `var-naming` +# to skip_list. +var_naming_pattern: "^[a-z_][a-z0-9_]*$" + +use_default_rules: true +# Load custom rules from this specific folder +# rulesdir: +# - ./rule/directory/ + +# Ansible-lint is able to recognize and load skip rules stored inside +# `.ansible-lint-ignore` (or `.config/ansible-lint-ignore.txt`) files. +# To skip a rule just enter filename and tag, like "playbook.yml package-latest" +# on a new line. +# Optionally you can add comments after the tag, prefixed by "#". We discourage +# the use of skip_list below because that will hide violations from the output. +# When putting ignores inside the ignore file, they are marked as ignored, but +# still visible, making it easier to address later. +skip_list: + - skip_this_tag + +# Ansible-lint does not automatically load rules that have the 'opt-in' tag. +# You must enable opt-in rules by listing each rule 'id' below. +enable_list: + - args + - empty-string-compare # opt-in + - no-log-password # opt-in + - no-same-owner # opt-in + - name[prefix] # opt-in + # add yaml here if you want to avoid ignoring yaml checks when yamllint + # library is missing. Normally its absence just skips using that rule. + - yaml +# Report only a subset of tags and fully ignore any others +# tags: +# - jinja[spacing] + +# Ansible-lint does not fail on warnings from the rules or tags listed below +warn_list: + - skip_this_tag + - experimental # experimental is included in the implicit list + # - role-name + # - yaml[document-start] # you can also use sub-rule matches + +# Some rules can transform files to fix (or make it easier to fix) identified +# errors. `ansible-lint --write` will reformat YAML files and run these transforms. +# By default it will run all transforms (effectively `write_list: ["all"]`). +# You can disable running transforms by setting `write_list: ["none"]`. +# Or only enable a subset of rule transforms by listing rules/tags here. +# write_list: +# - all + +# Offline mode disables installation of requirements.yml and schema refreshing +offline: true + +# Define required Ansible's variables to satisfy syntax check +extra_vars: + foo: bar + multiline_string_variable: | + line1 + line2 + complex_variable: ":{;\t$()" + +# Uncomment to enforce action validation with tasks, usually is not +# needed as Ansible syntax check also covers it. +# skip_action_validation: false + +# List of additional kind:pattern to be added at the top of the default +# match list, first match determines the file kind. +kinds: + # - playbook: "**/examples/*.{yml,yaml}" + # - galaxy: "**/folder/galaxy.yml" + # - tasks: "**/tasks/*.yml" + # - vars: "**/vars/*.yml" + # - meta: "**/meta/main.yml" + - yaml: "**/*.yaml-too" + +# List of additional collections to allow in only-builtins rule. +# only_builtins_allow_collections: +# - example_ns.example_collection + +# List of additions modules to allow in only-builtins rule. +# only_builtins_allow_modules: +# - example_module + +# Allow setting custom prefix for name[prefix] rule +task_name_prefix: "{stem} | " + diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg new file mode 100644 index 0000000..c7e2eec --- /dev/null +++ b/ansible/ansible.cfg @@ -0,0 +1,7 @@ +[defaults] +host_key_checking = false +roles_path = ./roles +playbook_dir = ./playbooks + +[ssh_connection] +pipelining = true diff --git a/ansible/archi.png b/ansible/archi.png Binary files differnew file mode 100644 index 0000000..8dc645a --- /dev/null +++ b/ansible/archi.png diff --git a/ansible/group_vars/all/vault b/ansible/group_vars/all/vault new file mode 100644 index 0000000..a7efee8 --- /dev/null +++ b/ansible/group_vars/all/vault @@ -0,0 +1,51 @@ +$ANSIBLE_VAULT;1.1;AES256 +32386366303436396463376337303465353739633630653431326336613661313938333838353366 +6666393836363265356631343134343337333635363165320a303230366434313563616566666336 +66623133353661386231366635396461363731666434373135396638373166383838323466613833 +3665393664623564620a316431626335646631616232313936333738383536643236343136323364 +35386435376566346435393661633662636435353936323335343337346338633561386638353565 +34656439306537333539666631663266333535646266336532303334343063336230306334663935 +30333732633734363335306237383133633035396339316139306137663535306439656236343035 +61616439316163353437383932353163333363643565386238613961623633333037393462386232 +33653536333637623931356533316664616336363035336432663165373634363435333564653038 +32653665656639313533323336616363623339303765323864356264336637633734333335353537 +36353639343233353638316466656664376363643561323731636437633661666335336235386263 +31653134363735663539396232633532356463656365663563353761303165326630643463383862 +34336435643033386664376563396535363363343338353233323535333466393136623864613965 +36396465393136343739353261333963613339616533656634376234663631646230323362373739 +31313639633931316465356130356432346161316532663864383038333566633639306266646339 +36323834386634376235666130366561383966623335316136663831643561336336333730313262 +34326166636430393334316234363330383962613864323132383463633931656464346531363164 +33633839363563346534636334623334316566643239316535666631366534366237316330386434 +63393234363936303935666462633035353965613136386665333938656232396130666537346630 +36323963303739376439333836643637376364326662303936383661333463343635326263653364 +63383937376435653964383134616433323666373639653136333533303039373063633735383465 +62306366613638633939313437306663616636623836316135386333383864633366613839653035 +36303934373363316132633662396561313431313137366662353733316233396238633564346335 +32346366383536386363663939653535363137613738333361356365386664326536646261333962 +31323737633033623138396339666465373763666434346561633838646635636230613731653337 +30393132386239333033356465663838393665656137316335326233313637643235613735326565 +63373663313533356139383833333135386536306636386233643430663437373837353261653532 +36386436633562386263623938653463323666323766323537623732643839306538623936663466 +65373036356265363063303466333836636431303864653964656534336464386238633562323931 +35636631643230393163366564393763643331616261333835363662306630303636363434336466 +36376133326135616430616139353533363361633937636563393362613032303833333831313430 +36363962623732656461663464353763303135646265613532623665373036663863616334343034 +37623535353438316663396165376432653362666438623233333362383934383564373836653437 +61666335633238323666353638613261343161616463643866343262633861303961363930326466 +64303431346637323761666564616164363833343139333536393039326262626231346638343864 +65663233323362343766613061343061626634303537353237623163356634643761663739393036 +32373465333337623032343064613663646230633038393134373231633664636565643266343034 +36656236323566336538313565346233313363353961313538313639616464306132613863336234 +37316134626439626662313930363335363864623936383563653636313736633564653838306161 +38303163646636616535313666666239646664313962396362356463353765396330326163613662 +61306535303730343436373461306333616462313332313634323464383163643439613864626530 +65386135613334316265333161383337313762383163356239353834653135653231653433663037 +63346335316564633835396630366433383139666465616639666432363462383138336435643332 +34353065613335386436613032633564343535613030643035313064666339346534643061636134 +34626639633039336632626235643763636635663530393536633763353864656530326235306234 +37663439333562343033353336373662346564396631626336356231613564383032636135303364 +32333437343636373136393439613833303231613465613635323164616234653264376134363332 +66353536613861343961343133343837653362363065356430363932353131333363306630333531 +62373864646364363765653931643838646563623438353036386631303664356635313538613561 +3163323132643861393837363333613862666464653434353262 diff --git a/ansible/group_vars/all/vault.example b/ansible/group_vars/all/vault.example new file mode 100644 index 0000000..3a21a43 --- /dev/null +++ b/ansible/group_vars/all/vault.example @@ -0,0 +1,26 @@ +# CHANGE THESE VARS AS PER YOUR DNS SETTINGS!! +vaultvar_root_domain: 'example.com' +vaultvar_vault_cname: 'vl' # ie. vl.example.com +vaultvar_torrents_cname: 'tor' +vaultvar_sonarr_cname: 'sarr' +vaultvar_radarr_cname: 'rarr' +vaultvar_nextcloud_cname: 'nx' +vaultvar_metrics_cname: 'met' + +vaultvar_minio_root_user: 'user' +vaultvar_minio_root_pass: 'password' +vaultvar_minio_nas_nfs_path: 'nas:/mnt/pool/set/minio' + +vaultvar_namecheap_user: 'username' +vaultvar_namecheap_api_tok: 'aabbccddeeffgghhiij123456' + +vaultvar_torrents_rpc_username: 'username' +vaultvar_torrents_rpc_password: 'aabbccddeeffgghhiij123456' + +vaultvar_nextcloud_nas_nfs_path: 'nas:/mnt/pool/set/nextcloud' + +vaultvar_plex_nas_nfs_path: 'nas:/mnt/pool/set/media' + +vaultvar_torrents_nas_nfs_path: 'nas:/mnt/pool/set/media' + +vaultvar_med_dl_nas_nfs_path: 'nas:/mnt/pool/set/media' diff --git a/ansible/hosts b/ansible/hosts new file mode 100644 index 0000000..5b96859 --- /dev/null +++ b/ansible/hosts @@ -0,0 +1,29 @@ +# These are just hosts created in the TF section. +# Replace these hostnames with your host names if required! + +[minio] +minio + +[sites] +sites + +[rproxy] +rproxy + +[monitoring] +monitoring + +[nc] +nc-kumar + +[plex] +plex + +[vault] +vault + +[torrents] +torrents + +[med-dl] +med-dl diff --git a/ansible/playbooks/init.yaml b/ansible/playbooks/init.yaml new file mode 100644 index 0000000..7e4029f --- /dev/null +++ b/ansible/playbooks/init.yaml @@ -0,0 +1,98 @@ +--- + +# ansible-playbook -u root -i 'hosts' --vault-id vaultkey playbooks/init.yaml --tags=vault +- name: 'Deploy Vault' + hosts: 'vault' + gather_facts: false + roles: + - role: 'base' + - role: 'docker' + - role: 'vault' + - role: 'caddy_add' + vars: + caddy_add_hosts: ['{{ vaultvar_vault_cname }}.{{ vaultvar_root_domain }}'] + caddy_add_upstream_host: '{{ inventory_hostname }}' + caddy_add_upstream_port: 8989 + +# ansible-playbook -u root -i 'hosts' --vault-id vaultkey playbooks/init.yaml --tags=torrents +- name: 'Deploy Transmission' + hosts: 'torrents' + gather_facts: false + roles: + - role: 'base' + - role: 'torrents' + vars: + torrents_nas_mount_path: '{{ vaultvar_torrents_nas_nfs_path }}' + torrents_rpc_username: '{{ vaultvar_torrents_rpc_username }}' + torrents_rpc_password: '{{ vaultvar_torrents_rpc_password }}' + - role: 'caddy_add' + vars: + caddy_add_hosts: ['{{ vaultvar_torrents_cname }}.{{ vaultvar_root_domain }}'] + caddy_add_upstream_host: '{{ inventory_hostname }}' + +# ansible-playbook -u root -i 'hosts' --vault-id vaultkey playbooks/init.yaml --tags=med_dl +- name: 'Deploy Media Downloaders' + hosts: 'med-dl' + gather_facts: false + roles: + - role: 'base' + - role: 'docker' + - role: 'med_dl' + vars: + med_dl_nas_mount_path: '{{ vaultvar_med_dl_nas_nfs_path }}' + - role: 'caddy_add' + vars: + caddy_add_hosts: ['{{ vaultvar_sonarr_cname }}.{{ vaultvar_root_domain }}'] + caddy_add_upstream_host: '{{ inventory_hostname }}' + caddy_add_upstream_port: 8989 + - role: 'caddy_add' + vars: + caddy_add_hosts: ['{{ vaultvar_radarr_cname }}.{{ vaultvar_root_domain }}'] + caddy_add_upstream_host: '{{ inventory_hostname }}' + caddy_add_upstream_port: 7878 + +# ansible-playbook -u root -i 'hosts' --vault-id vaultkey playbooks/init.yaml --tags=nextcloud +- name: 'Deploy Nextcloud' + hosts: 'nc' + gather_facts: false + roles: + - role: 'base' + - role: 'docker' + - role: 'nextcloud' + vars: + nextcloud_nas_mount_path: '{{ vaultvar_nextcloud_nas_nfs_path }}' + nextcloud_php_max_mem_mb: 8000 + nextcloud_php_max_upload_size_gb: 10 + # You should have DRI devices showing up in your container in `/dev/dri/`. + # See the TF readme for steps to enable this. + # If not, then set this to false here. + # Leave this as a yaml string, it is going to used as a shell var. + nextcloud_enable_dri: 'true' + - role: 'caddy_add' + vars: + caddy_add_hosts: ['{{ vaultvar_nextcloud_cname }}.{{ vaultvar_root_domain }}'] + caddy_add_upstream_host: '{{ inventory_hostname }}' + caddy_add_upstream_port: 11000 + +# ansible-playbook -u root -i 'hosts' --vault-id vaultkey playbooks/init.yaml --tags=plex +- name: 'Deploy Plex' + hosts: 'plex' + gather_facts: false + roles: + - role: 'base' + - role: 'plex' + vars: + plex_nas_mount_path: '{{ vaultvar_plex_nas_nfs_path }}' + +# ansible-playbook -u root -i 'hosts' --vault-id vaultkey playbooks/init.yaml --tags=monitoring +- name: 'Deploy Prometheus' + hosts: 'monitoring' + gather_facts: false + roles: + - role: 'base' + - role: 'monitoring' + - role: 'caddy_add' + vars: + caddy_add_hosts: ['{{ vaultvar_metrics_cname }}.{{ vaultvar_root_domain }}'] + caddy_add_upstream_host: '{{ inventory_hostname }}' + caddy_add_upstream_port: 9090 diff --git a/ansible/roles/base/tasks/main.yaml b/ansible/roles/base/tasks/main.yaml new file mode 100644 index 0000000..b5aaf97 --- /dev/null +++ b/ansible/roles/base/tasks/main.yaml @@ -0,0 +1,12 @@ +--- + +- tags: 'always' + # noqa: name[missing] + block: + - name: 'Install some useful packages' + ansible.builtin.apt: + name: + - 'tcpdump' + - 'curl' + state: 'present' + update_cache: true diff --git a/ansible/roles/caddy_add/tasks/main.yaml b/ansible/roles/caddy_add/tasks/main.yaml new file mode 100644 index 0000000..80382d4 --- /dev/null +++ b/ansible/roles/caddy_add/tasks/main.yaml @@ -0,0 +1,64 @@ +--- + +- tags: 'always' + # noqa: name[missing] + block: + - name: 'Ensure required vars are set' + ansible.builtin.assert: + that: + - item | mandatory + loop: + - '{{ caddy_add_hosts }}' + - '{{ caddy_add_upstream_host }}' + - '{{ caddy_add_upstream_port }}' + + - name: 'Call the Caddy API to add our new host' + ansible.builtin.uri: + url: 'http://rproxy:2019/config/apps/http/servers/serv0/routes' + method: 'PUT' + body_format: 'json' + status_code: 200 + body: | + { + "match": [ + { + "host": {{ caddy_add_hosts | to_json }} + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "reverse_proxy", + "upstreams": [ + { + "dial": "{{ caddy_add_upstream_host }}:{{ caddy_add_upstream_port }}" + } + ] + } + ] + } + ] + } + ], + "terminal": true + } + + - name: 'Get a copy of the new Caddy config' + delegate_to: 'localhost' + ansible.builtin.uri: + url: 'http://rproxy:2019/config' + return_content: true + register: '_current_conf' + + - name: 'Save the new config to file' + delegate_to: 'localhost' + ansible.builtin.copy: + dest: 'artifacts/caddy/{{ _file_name }}' + content: '{{ _current_conf.json }}' + mode: '644' + vars: + _file_name: 'v{{ lookup("pipe", "date +%Y%m%dT%H%M%S") }}.json' diff --git a/ansible/roles/docker/tasks/main.yaml b/ansible/roles/docker/tasks/main.yaml new file mode 100644 index 0000000..bb5b55b --- /dev/null +++ b/ansible/roles/docker/tasks/main.yaml @@ -0,0 +1,34 @@ +--- + +- tags: 'always' + # noqa: name[missing] + block: + - name: 'Install some prereqs' + ansible.builtin.package: + name: + - 'ca-certificates' + - 'gnupg' + state: 'present' + + - name: 'Run Docker installer' + ansible.builtin.shell: + cmd: | + curl -fsSL https://get.docker.com | sh + creates: '/var/run/docker.sock' + + - name: 'Docker set MTU' + ansible.builtin.copy: + dest: '/etc/docker/daemon.json' + content: | + {"mtu": 1420} + mode: '644' + + - name: 'Restart Docker service' + ansible.builtin.service: + name: 'docker' + state: 'restarted' + + - name: 'Install docker-compose' + ansible.builtin.package: + name: 'docker-compose' + state: 'present' diff --git a/ansible/roles/med_dl/tasks/main.yaml b/ansible/roles/med_dl/tasks/main.yaml new file mode 100644 index 0000000..c4d4a7f --- /dev/null +++ b/ansible/roles/med_dl/tasks/main.yaml @@ -0,0 +1,5 @@ +--- + +- name: 'Run the setup tasks' + ansible.builtin.import_tasks: 'setup.yaml' + tags: 'med_dl' diff --git a/ansible/roles/med_dl/tasks/setup.yaml b/ansible/roles/med_dl/tasks/setup.yaml new file mode 100644 index 0000000..46affac --- /dev/null +++ b/ansible/roles/med_dl/tasks/setup.yaml @@ -0,0 +1,38 @@ +--- + +- name: 'setup | Ensure required vars are set' + ansible.builtin.assert: + that: + - item | mandatory + loop: + - '{{ med_dl_nas_mount_path }}' + no_log: true + +- name: 'setup | Install required pkgs' + ansible.builtin.package: + name: + - 'nfs-common' + +- name: 'setup | Create the mount dir' + ansible.builtin.file: + path: '/mnt/data' + state: 'directory' + mode: '755' + +- name: 'setup | Setup the NFS mount' + ansible.posix.mount: + src: '{{ med_dl_nas_mount_path }}' + path: '/mnt/data' + state: 'mounted' + fstype: 'nfs' + +- name: 'setup | Copy the docker-compose file' + ansible.builtin.template: + src: 'docker-compose.yaml.j2' + dest: 'docker-compose.yaml' + mode: '644' + +- name: 'setup | Start the service' + ansible.builtin.command: 'docker-compose up -d' + register: '_compose_up_cmd' + changed_when: '_compose_up_cmd.rc == 0' diff --git a/ansible/roles/med_dl/templates/docker-compose.yaml.j2 b/ansible/roles/med_dl/templates/docker-compose.yaml.j2 new file mode 100644 index 0000000..fa25db0 --- /dev/null +++ b/ansible/roles/med_dl/templates/docker-compose.yaml.j2 @@ -0,0 +1,67 @@ +{{ ansible_managed | comment }} +version: "3" +services: + prowlarr: + image: lscr.io/linuxserver/prowlarr:latest + restart: unless-stopped + container_name: prowlarr + volumes: + - prowlarr-config:/config + ports: + - 9696:9696 + environment: + - PUID=1001 + - PGID=1001 + - TZ=Etc/UTC + networks: + - med-dl + + radarr: + image: lscr.io/linuxserver/radarr:latest + restart: unless-stopped + container_name: radarr + volumes: + - radarr-config:/config + - /mnt/data/downloads:/mnt/data/downloads + - /mnt/data/mov:/mov + ports: + - 7878:7878 + environment: + - PUID=1001 + - PGID=1001 + - TZ=Etc/UTC + networks: + - med-dl + + sonarr: + image: lscr.io/linuxserver/sonarr:latest + restart: unless-stopped + container_name: sonarr + volumes: + - sonarr-config:/config + - /mnt/data/downloads:/mnt/data/downloads + - /mnt/data/tv:/tv + ports: + - 8989:8989 + environment: + - PUID=1001 + - PGID=1001 + - TZ=Etc/UTC + networks: + - med-dl + +volumes: + prowlarr-config: + name: prowlarr-config + radarr-config: + name: radarr-config + sonarr-config: + name: sonarr-config + +networks: + med-dl: + name: med-dl + driver: bridge + driver_opts: + com.docker.network.driver.mtu: 1420 + diff --git a/ansible/roles/monitoring/tasks/main.yaml b/ansible/roles/monitoring/tasks/main.yaml new file mode 100644 index 0000000..256a09f --- /dev/null +++ b/ansible/roles/monitoring/tasks/main.yaml @@ -0,0 +1,5 @@ +--- + +- name: 'Run the setup tasks' + ansible.builtin.import_tasks: 'setup.yaml' + tags: 'monitoring' diff --git a/ansible/roles/monitoring/tasks/setup.yaml b/ansible/roles/monitoring/tasks/setup.yaml new file mode 100644 index 0000000..824d2db --- /dev/null +++ b/ansible/roles/monitoring/tasks/setup.yaml @@ -0,0 +1,20 @@ +--- + +- name: 'setup | Install required pkgs' + ansible.builtin.package: + name: + - 'prometheus' + - 'prometheus-node-exporter' + - 'prometheus-blackbox-exporter' + +- name: 'setup | Set the Prom config' + ansible.builtin.template: + src: 'prometheus.yml.j2' + dest: '/etc/prometheus/prometheus.yml' + mode: '644' + +- name: 'setup | Start the service' + ansible.builtin.service: + name: 'prometheus' + state: 'restarted' + enabled: true diff --git a/ansible/roles/monitoring/templates/prometheus.yml.j2 b/ansible/roles/monitoring/templates/prometheus.yml.j2 new file mode 100644 index 0000000..a5f3b46 --- /dev/null +++ b/ansible/roles/monitoring/templates/prometheus.yml.j2 @@ -0,0 +1,47 @@ +{{ ansible_managed | comment }} +global: + scrape_interval: 1m + evaluation_interval: 1m + # scrape_timeout is set to the global default (10s). + + # Attach these labels to any time series or alerts when communicating with + # external systems (federation, remote storage, Alertmanager). + external_labels: + monitor: 'example' + +# Alertmanager configuration +alerting: + alertmanagers: + - static_configs: + - targets: ['localhost:9093'] + +# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. +rule_files: + # - "first_rules.yml" + # - "second_rules.yml" + +# A scrape configuration containing exactly one endpoint to scrape: +# Here it's Prometheus itself. +scrape_configs: + # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. + - job_name: 'prometheus' + + # Override the global default and scrape targets from this job every 5 seconds. + # scrape_interval: 30s + # scrape_timeout: 30s + + # metrics_path defaults to '/metrics' + # scheme defaults to 'http'. + + static_configs: + - targets: ['localhost:9090'] + + - job_name: node + # If prometheus-node-exporter is installed, grab stats about the local + # machine by default. + static_configs: + - targets: ['localhost:9100'] + + - job_name: caddy + static_configs: + - targets: ['rproxy:2019', 'sites:2019'] diff --git a/ansible/roles/nextcloud/tasks/main.yaml b/ansible/roles/nextcloud/tasks/main.yaml new file mode 100644 index 0000000..0d3697b --- /dev/null +++ b/ansible/roles/nextcloud/tasks/main.yaml @@ -0,0 +1,5 @@ +--- + +- name: 'Run the setup tasks' + ansible.builtin.import_tasks: 'setup.yaml' + tags: 'nextcloud' diff --git a/ansible/roles/nextcloud/tasks/setup.yaml b/ansible/roles/nextcloud/tasks/setup.yaml new file mode 100644 index 0000000..ac17702 --- /dev/null +++ b/ansible/roles/nextcloud/tasks/setup.yaml @@ -0,0 +1,40 @@ +--- + +- name: 'setup | Ensure required vars are set' + ansible.builtin.assert: + that: + - item | mandatory + loop: + - '{{ nextcloud_nas_mount_path }}' + - '{{ nextcloud_php_max_mem_mb }}' + - '{{ nextcloud_php_max_upload_size_gb }}' + no_log: true + +- name: 'setup | Install required pkgs' + ansible.builtin.package: + name: + - 'nfs-common' + +- name: 'setup | Create the mount dir' + ansible.builtin.file: + path: '/mnt/data' + state: 'directory' + mode: '755' + +- name: 'setup | Setup the NFS mount' + ansible.posix.mount: + src: '{{ nextcloud_nas_mount_path }}' + path: '/mnt/data' + state: 'mounted' + fstype: 'nfs' + +- name: 'setup | Copy the docker-compose file' + ansible.builtin.template: + src: 'docker-compose.yaml.j2' + dest: 'docker-compose.yaml' + mode: '644' + +- name: 'setup | Start the service' + ansible.builtin.command: 'docker-compose up -d' + register: '_compose_up_cmd' + changed_when: '_compose_up_cmd.rc == 0' diff --git a/ansible/roles/nextcloud/templates/docker-compose.yaml.j2 b/ansible/roles/nextcloud/templates/docker-compose.yaml.j2 new file mode 100644 index 0000000..3571432 --- /dev/null +++ b/ansible/roles/nextcloud/templates/docker-compose.yaml.j2 @@ -0,0 +1,41 @@ +{{ ansible_managed | comment }} +version: "3" +services: + nextcloud: + image: nextcloud/all-in-one:latest + restart: always + container_name: nextcloud-aio-mastercontainer + volumes: + - nextcloud_aio_mastercontainer:/mnt/docker-aio-config + - /var/run/docker.sock:/var/run/docker.sock:ro + ports: + - 8080:8080 + environment: + - APACHE_PORT=11000 + - APACHE_IP_BINDING=0.0.0.0 + - COLLABORA_SECCOMP_DISABLED=true + - NEXTCLOUD_DATADIR=/mnt/data + - NEXTCLOUD_MOUNT=/mnt/ + - NEXTCLOUD_UPLOAD_LIMIT={{ nextcloud_php_max_upload_size_gb }}G + - NEXTCLOUD_MAX_TIME=3600 + - NEXTCLOUD_MEMORY_LIMIT={{ nextcloud_php_max_mem_mb }}M + - NEXTCLOUD_STARTUP_APPS=deck twofactor_totp tasks calendar contacts notes memories richdocuments -photos + - NEXTCLOUD_ADDITIONAL_APKS=imagemagick + - NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS=imagick + - NEXTCLOUD_ENABLE_DRI_DEVICE={{ nextcloud_enable_dri }} + - TALK_PORT=3478 + - WATCHTOWER_DOCKER_SOCKET_PATH=/var/run/docker.sock + - SKIP_DOMAIN_VALIDATION=true + networks: + - nextcloud-aio + +volumes: + nextcloud_aio_mastercontainer: + name: nextcloud_aio_mastercontainer + +networks: + nextcloud-aio: + name: nextcloud-aio + driver: bridge + driver_opts: + com.docker.network.driver.mtu: 1420 diff --git a/ansible/roles/plex/tasks/main.yaml b/ansible/roles/plex/tasks/main.yaml new file mode 100644 index 0000000..5469534 --- /dev/null +++ b/ansible/roles/plex/tasks/main.yaml @@ -0,0 +1,5 @@ +--- + +- name: 'Run the setup tasks' + ansible.builtin.import_tasks: 'setup.yaml' + tags: 'plex' diff --git a/ansible/roles/plex/tasks/setup.yaml b/ansible/roles/plex/tasks/setup.yaml new file mode 100644 index 0000000..de0eb69 --- /dev/null +++ b/ansible/roles/plex/tasks/setup.yaml @@ -0,0 +1,55 @@ +--- + +- name: 'setup | Ensure required vars are set' + ansible.builtin.assert: + that: + - item | mandatory + loop: + - '{{ plex_nas_mount_path }}' + no_log: true + +- name: 'setup | Install required pkgs' + ansible.builtin.package: + name: + - 'nfs-common' + - 'curl' + - 'gnupg' + +- name: 'setup | Create the mount dir' + ansible.builtin.file: + path: '/mnt/data' + state: 'directory' + mode: '755' + +- name: 'setup | Setup the NFS mount' + ansible.posix.mount: + src: '{{ plex_nas_mount_path }}' + path: '/mnt/data' + state: 'mounted' + fstype: 'nfs' + +- name: 'setup | Get the Plex signed keys' + ansible.builtin.shell: + # noqa: risky-shell-pipe command-instead-of-module + cmd: > + curl -sS https://downloads.plex.tv/plex-keys/PlexSign.key | gpg --dearmor | tee /usr/share/keyrings/plex.gpg > /dev/null + creates: '/usr/share/keyrings/plex.gpg' + +- name: 'setup | Set the Plex sources' + ansible.builtin.copy: + dest: '/etc/apt/sources.list.d/plexmediaserver.list' + content: | + deb [signed-by=/usr/share/keyrings/plex.gpg] https://downloads.plex.tv/repo/deb public main + mode: '644' + +- name: 'setup | Install the package' + ansible.builtin.apt: + name: 'plexmediaserver' + state: 'present' + update_cache: true + +- name: 'setup | Start the service' + ansible.builtin.service: + name: 'plexmediaserver' + state: 'stopped' + enabled: true diff --git a/ansible/roles/torrents/tasks/main.yaml b/ansible/roles/torrents/tasks/main.yaml new file mode 100644 index 0000000..806a4e3 --- /dev/null +++ b/ansible/roles/torrents/tasks/main.yaml @@ -0,0 +1,5 @@ +--- + +- name: 'Run the setup tasks' + ansible.builtin.import_tasks: 'setup.yaml' + tags: 'torrents' diff --git a/ansible/roles/torrents/tasks/setup.yaml b/ansible/roles/torrents/tasks/setup.yaml new file mode 100644 index 0000000..25f1fe8 --- /dev/null +++ b/ansible/roles/torrents/tasks/setup.yaml @@ -0,0 +1,79 @@ +--- + +- name: 'setup | Ensure required vars are set' + ansible.builtin.assert: + that: + - item | mandatory + loop: + - '{{ torrents_nas_mount_path }}' + - '{{ torrents_rpc_username }}' + - '{{ torrents_rpc_password }}' + no_log: true + +- name: 'setup | Install required pkgs' + ansible.builtin.package: + name: + - 'nfs-common' + - 'transmission-daemon' + +- name: 'setup | Stop the transmission-daemon service' + ansible.builtin.service: + name: 'transmission-daemon' + state: 'stopped' + +- name: 'setup | Create the mount dir' + ansible.builtin.file: + path: '/mnt/data' + state: 'directory' + mode: '755' + +- name: 'setup | Setup the NFS mount' + ansible.posix.mount: + src: '{{ torrents_nas_mount_path }}' + path: '/mnt/data' + state: 'mounted' + fstype: 'nfs' + +- name: 'setup | Create new user for transmission' + ansible.builtin.user: + name: 'transmission-user' + uid: 1001 + groups: 'users' + create_home: true + +- name: 'setup | Fix the service file to use our user' + ansible.builtin.lineinfile: + path: '/lib/systemd/system/transmission-daemon.service' + regexp: '^User=' + line: 'User=transmission-user' + +- name: 'setup | Reload systemd daemon' + ansible.builtin.systemd: + daemon_reload: true + +# THis is kind of a hack to force the generation of +# /home/transmission-user/.config/transmission-daemon dirs +# so that we can place our config file there. +- name: 'setup | Start the service' + ansible.builtin.service: + name: 'transmission-daemon' + state: 'started' + +# We still need to stop it to place the config file or else it will get overwritten +- name: 'setup | Stop the service' + ansible.builtin.service: + name: 'transmission-daemon' + state: 'stopped' + +- name: 'setup | Copy the transmission config' + ansible.builtin.template: + src: 'settings.json.j2' + dest: '/home/transmission-user/.config/transmission-daemon/settings.json' + owner: 'transmission-user' + mode: '644' + +- name: 'setup | Start the service' + ansible.builtin.service: + name: 'transmission-daemon' + state: 'started' + enabled: true diff --git a/ansible/roles/torrents/templates/settings.json.j2 b/ansible/roles/torrents/templates/settings.json.j2 new file mode 100644 index 0000000..cf5ea4b --- /dev/null +++ b/ansible/roles/torrents/templates/settings.json.j2 @@ -0,0 +1,73 @@ +{ + "alt-speed-down": 50, + "alt-speed-enabled": false, + "alt-speed-time-begin": 540, + "alt-speed-time-day": 127, + "alt-speed-time-enabled": false, + "alt-speed-time-end": 1020, + "alt-speed-up": 50, + "bind-address-ipv4": "0.0.0.0", + "bind-address-ipv6": "::", + "blocklist-enabled": false, + "blocklist-url": "http://www.example.com/blocklist", + "cache-size-mb": 4, + "dht-enabled": true, + "download-dir": "/mnt/data/downloads", + "download-limit": 100, + "download-limit-enabled": 0, + "download-queue-enabled": true, + "download-queue-size": 5, + "encryption": 1, + "idle-seeding-limit": 30, + "idle-seeding-limit-enabled": false, + "incomplete-dir": "/home/transmission-user/downloads", + "incomplete-dir-enabled": false, + "lpd-enabled": false, + "max-peers-global": 200, + "message-level": 1, + "peer-congestion-algorithm": "", + "peer-id-ttl-hours": 6, + "peer-limit-global": 200, + "peer-limit-per-torrent": 50, + "peer-port": 51413, + "peer-port-random-high": 65535, + "peer-port-random-low": 49152, + "peer-port-random-on-start": false, + "peer-socket-tos": "default", + "pex-enabled": true, + "port-forwarding-enabled": false, + "preallocation": 1, + "prefetch-enabled": true, + "queue-stalled-enabled": true, + "queue-stalled-minutes": 30, + "ratio-limit": 2, + "ratio-limit-enabled": false, + "rename-partial-files": true, + "rpc-authentication-required": true, + "rpc-bind-address": "0.0.0.0", + "rpc-enabled": true, + "rpc-host-whitelist": "", + "rpc-host-whitelist-enabled": true, + "rpc-password": "{{ torrents_rpc_password }}", + "rpc-port": 9091, + "rpc-url": "/transmission/", + "rpc-username": "{{ torrents_rpc_username }}", + "rpc-whitelist": "*", + "rpc-whitelist-enabled": true, + "scrape-paused-torrents-enabled": true, + "script-torrent-done-enabled": false, + "script-torrent-done-filename": "", + "seed-queue-enabled": false, + "seed-queue-size": 10, + "speed-limit-down": 100, + "speed-limit-down-enabled": false, + "speed-limit-up": 100, + "speed-limit-up-enabled": false, + "start-added-torrents": true, + "trash-original-torrent-files": false, + "umask": 18, + "upload-limit": 100, + "upload-limit-enabled": 0, + "upload-slots-per-torrent": 14, + "utp-enabled": true +} diff --git a/ansible/roles/vault/tasks/main.yaml b/ansible/roles/vault/tasks/main.yaml new file mode 100644 index 0000000..191bbc1 --- /dev/null +++ b/ansible/roles/vault/tasks/main.yaml @@ -0,0 +1,5 @@ +--- + +- name: 'Run the setup tasks' + ansible.builtin.import_tasks: 'setup.yaml' + tags: 'vault' diff --git a/ansible/roles/vault/tasks/setup.yaml b/ansible/roles/vault/tasks/setup.yaml new file mode 100644 index 0000000..f05aeee --- /dev/null +++ b/ansible/roles/vault/tasks/setup.yaml @@ -0,0 +1,12 @@ +--- + +- name: 'setup | Copy the docker-compose file' + ansible.builtin.template: + src: 'docker-compose.yaml.j2' + dest: 'docker-compose.yaml' + mode: '644' + +- name: 'setup | Start the service' + ansible.builtin.command: 'docker-compose up -d' + register: '_compose_up_cmd' + changed_when: '_compose_up_cmd.rc == 0' diff --git a/ansible/roles/vault/templates/docker-compose.yaml.j2 b/ansible/roles/vault/templates/docker-compose.yaml.j2 new file mode 100644 index 0000000..7c9d74c --- /dev/null +++ b/ansible/roles/vault/templates/docker-compose.yaml.j2 @@ -0,0 +1,28 @@ +{{ ansible_managed | comment }} +version: "3" +services: + vaultwarden: + image: vaultwarden/server:latest + restart: always + container_name: vaultwarden + volumes: + - vaultwarden:/data + ports: + - 8989:80 + environment: + - WEBSOCKET_ENABLED=true + - INVITATIONS_ALLOWED=true + - SIGNUPS_ALLOWED=true + networks: + - vaultwarden + +volumes: + vaultwarden: + name: vaultwarden + +networks: + vaultwarden: + name: vaultwarden + driver: bridge + driver_opts: + com.docker.network.driver.mtu: 1420 |
