diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..03e5b4f --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,111 @@ +--- +# .ansible-lint + +profile: null # min, basic, moderate,safety, shared, production + +# 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 + - .github/ + - 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 + +# Enable checking of loop variable prefixes in roles +loop_var_prefix: "{role}_" + +# 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 completely ignores rules or tags listed below +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: + - empty-string-compare # opt-in + - no-log-password # opt-in + - no-same-owner # 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 +offline: false + +# Return success if number of violations compared with previous git +# commit has not increased. This feature works only in git +# repositories. +progressive: false + +# 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 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9e0226e..6a544c3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ playbook.retry *.sw* .vagrant/ *.log +.idea/ +venv/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..6b4fbd3 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,14 @@ +repos: + +#- repo: https://github.com/semaphor-dk/dansabel +# rev: b72c70351d1a9e32a75db505fcb3aa414f3282f8 +# hooks: +# - id: dansabel + +- repo: https://github.com/ansible/ansible-lint + rev: v6.9.0 + hooks: + - id: ansible-lint + files: \.(yaml|yml)$ + additional_dependencies: + - ansible diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4c47f67 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +init: create_venv install_pre_commit install_ansible_galaxy_modules + +create_venv: + python3 -m venv venv + venv/bin/pip install -U pip + venv/bin/pip install ansible pre-commit + +install_pre_commit: + venv/bin/pre-commit install + +install_ansible_galaxy_modules: + venv/bin/ansible-galaxy collection install community.general \ No newline at end of file diff --git a/deploy.sh b/deploy.sh index 70095a1..3649dc5 100755 --- a/deploy.sh +++ b/deploy.sh @@ -18,7 +18,7 @@ else $BASE_CMD --tags setup_services else echo "Deploying services: $2" - $BASE_CMD --tags setup_services --extra-vars "services=$2" + $BASE_CMD --tags setup_services --extra-vars "enabled_services=$2" fi ;; "base") diff --git a/playbook.yml b/playbook.yml index 1ce47fb..d96776b 100644 --- a/playbook.yml +++ b/playbook.yml @@ -13,6 +13,31 @@ smtp_host: "postfix" smtp_port: "587" + enabled_services: + - nginx_proxy + - postfix + - openldap + - keycloak + - restic_backup + - nextcloud + - passit + - gitea + - matrix_riot + - privatebin + - codimd + - hedgedoc + - netdata + - docker_registry + - drone + - websites + - ulovliglogning-dk + - watchtower + - mailu + - portainer + - mastodon + - rallly + - membersystem + tasks: - import_role: name: ubuntu_base diff --git a/roles/docker/defaults/main.yml b/roles/docker/defaults/main.yml index e87ad37..2a23950 100644 --- a/roles/docker/defaults/main.yml +++ b/roles/docker/defaults/main.yml @@ -4,6 +4,9 @@ volume_root_folder: "/docker-volumes" services: ### Internal services ### + postfix: + file: postfix.yml + version: "v3.5.0" nginx_proxy: file: nginx_proxy.yml @@ -39,16 +42,13 @@ services: volume_folder: "{{ volume_root_folder }}/keycloak" version: "20.0" - postfix: - file: postfix.yml - version: "v3.5.0" - restic: file: restic_backup.yml user: "datacoop" domain: "restic.cannedtuna.org" repository: "datacoop-hevonen" version: "1.6.0" + disabled_in_vagrant: true docker_registry: file: docker_registry.yml @@ -71,12 +71,14 @@ services: domain: "git.{{ base_domain }}" volume_folder: "{{ volume_root_folder }}/gitea" version: 1.17.3 + allowed_sender_domain: true passit: file: passit.yml domain: "passit.{{ base_domain }}" volume_folder: "{{ volume_root_folder }}/passit" version: stable + allowed_sender_domain: true matrix: file: matrix_riot.yml @@ -105,7 +107,7 @@ services: file: hedgedoc.yml domain: "pad.{{ base_domain }}" volume_folder: "{{ volume_root_folder }}/hedgedoc" - version: 1.9.0 + version: 1.9.6 data_coop_website: file: websites/data.coop.yml @@ -151,14 +153,17 @@ services: domain: "social.{{ base_domain }}" volume_folder: "{{ volume_root_folder }}/mastodon" version: v4.0.2 + allowed_sender_domain: true rallly: file: rallly.yml domain: "when.{{ base_domain }}" volume_folder: "{{ volume_root_folder }}/rallly" version: a21f92bf74308d66cfcd545d49b81eba0211a222 + allowed_sender_domain: true membersystem: file: membersystem.yml domain: "member.{{ base_domain }}" django_admins: "Vidir:valberg@orn.li" + allowed_sender_domain: true diff --git a/roles/docker/files/configs/mastodon/env_file.j2 b/roles/docker/files/configs/mastodon/env_file.j2 index e894d0d..58436c4 100644 --- a/roles/docker/files/configs/mastodon/env_file.j2 +++ b/roles/docker/files/configs/mastodon/env_file.j2 @@ -14,7 +14,7 @@ # ---------- # This identifies your server and cannot be changed safely later # ---------- -LOCAL_DOMAIN={{ mastodon.domain }} +LOCAL_DOMAIN={{ services.mastodon.domain }} # Redis # ----- @@ -52,7 +52,7 @@ SMTP_SERVER={{ smtp_host }} SMTP_PORT={{ smtp_port }} SMTP_LOGIN= SMTP_PASSWORD= -SMTP_FROM_ADDRESS=notifications@{{ mastodon.domain }} +SMTP_FROM_ADDRESS=notifications@{{ services.mastodon.domain }} # File storage (optional) # ----------------------- diff --git a/roles/docker/files/configs/matrix/homeserver.yaml.j2 b/roles/docker/files/configs/matrix/homeserver.yaml.j2 index 44c22c2..4b8c3aa 100644 --- a/roles/docker/files/configs/matrix/homeserver.yaml.j2 +++ b/roles/docker/files/configs/matrix/homeserver.yaml.j2 @@ -44,7 +44,7 @@ pid_file: /data/homeserver.pid # use synapse with a reverse proxy, this should be the URL to reach # synapse via the proxy. # -public_baseurl: "https://{{ matrix.domain }}" +public_baseurl: "https://{{ services.matrix.domain }}" # Set the soft limit on the number of file descriptors synapse can use # Zero is used to indicate synapse should set the soft limit to the diff --git a/roles/docker/files/configs/rallly/env_file b/roles/docker/files/configs/rallly/env_file index e0cced2..6403696 100644 --- a/roles/docker/files/configs/rallly/env_file +++ b/roles/docker/files/configs/rallly/env_file @@ -1,7 +1,7 @@ -NEXT_PUBLIC_BASE_URL="https://{{ rallly.domain }}" +NEXT_PUBLIC_BASE_URL="https://{{ services.rallly.domain }}" DATABASE_URL="postgres://postgres:{{ postgres_passwords.rallly }}@rallly_db:5432/rallly_db" SECRET_PASSWORD="{{ rallly_secrets.secret_password }}" -SUPPORT_EMAIL="noreply@{{ rallly.domain }}" +SUPPORT_EMAIL="noreply@{{ services.rallly.domain }}" SMTP_HOST="{{ smtp_host }}" SMTP_PORT="{{ smtp_port }}" SMTP_SECURE="false" diff --git a/roles/docker/files/configs/riot/config.json b/roles/docker/files/configs/riot/config.json index 0ea4d1a..f88e420 100644 --- a/roles/docker/files/configs/riot/config.json +++ b/roles/docker/files/configs/riot/config.json @@ -1,7 +1,7 @@ { "default_server_config": { "m.homeserver": { - "base_url": "https://{{ matrix.domain }}" + "base_url": "https://{{ services.matrix.domain }}" }, "m.identity_server": { "base_url": "https://vector.im" @@ -37,7 +37,7 @@ ] }, "enable_presence_by_hs_url": { - "https://{{ matrix.domain }}": false + "https://{{ services.matrix.domain }}": false }, "terms_and_conditions_links": [ { diff --git a/roles/docker/tasks/services.yml b/roles/docker/tasks/services.yml index 6b084f2..73537b0 100644 --- a/roles/docker/tasks/services.yml +++ b/roles/docker/tasks/services.yml @@ -3,7 +3,12 @@ docker_network: name: external_services +#- name: setup services +# include_tasks: "services/{{ item.value.file }}" +# loop: "{{ services | dict2items }}" +# when: item.key in enabled_services and item.value.file is defined and item.value.disabled_in_vagrant is not defined + - name: setup services - include_tasks: "services/{{ item.value.file }}" - loop: "{{ services | dict2items }}" - when: item.value.file is defined + include_tasks: "services/{{ services[item].file }}" + loop: "{{ enabled_services }}" + when: item in services and services[item].file is defined and services[item].disabled_in_vagrant is not defined diff --git a/roles/docker/tasks/services/docker_registry.yml b/roles/docker/tasks/services/docker_registry.yml index 5d7d769..660e684 100644 --- a/roles/docker/tasks/services/docker_registry.yml +++ b/roles/docker/tasks/services/docker_registry.yml @@ -30,7 +30,6 @@ - name: log in to registry docker_login: - registry: "{{ services.docker_registry.domain }}" + registry: "{{ 'docker.data.coop' if vagrant else services.docker_registry.domain }}" username: "docker" password: "{{ docker_password }}" - config_path: "{{ services.docker_registry.volume_folder }}/auth/config.json" diff --git a/roles/docker/tasks/services/membersystem.yml b/roles/docker/tasks/services/membersystem.yml index 671b026..ca63851 100644 --- a/roles/docker/tasks/services/membersystem.yml +++ b/roles/docker/tasks/services/membersystem.yml @@ -25,14 +25,14 @@ POSTGRES_PORT: 5432 EMAIL_BACKEND: "django.core.mail.backends.smtp.EmailBackend" EMAIL_URL: "smtp://noop@{{ smtp_host }}:{{ smtp_port }}" - VIRTUAL_HOST: "{{ membersystem.domain }}" + VIRTUAL_HOST: "{{ services.membersystem.domain }}" VIRTUAL_PORT: "8000" - LETSENCRYPT_HOST: "{{ membersystem.domain }}" + LETSENCRYPT_HOST: "{{ services.membersystem.domain }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" - ALLOWED_HOSTS: "{{ membersystem.domain }}" - CSRF_TRUSTED_ORIGINS: "https://{{ membersystem.domain }}" - DJANGO_ADMINS: "{{ membersystem.django_admins }}" - DEFAULT_FROM_EMAIL: "noreply@{{ membersystem.domain }}" + ALLOWED_HOSTS: "{{ services.membersystem.domain }}" + CSRF_TRUSTED_ORIGINS: "https://{{ services.membersystem.domain }}" + DJANGO_ADMINS: "{{ services.membersystem.django_admins }}" + DEFAULT_FROM_EMAIL: "noreply@{{ services.membersystem.domain }}" labels: com.centurylinklabs.watchtower.enable: "true" diff --git a/roles/docker/tasks/services/nextcloud.yml b/roles/docker/tasks/services/nextcloud.yml index a11ca1b..d36f8de 100644 --- a/roles/docker/tasks/services/nextcloud.yml +++ b/roles/docker/tasks/services/nextcloud.yml @@ -39,7 +39,7 @@ networks: - "nextcloud" volumes: - - "{{ nextcloud.volume_folder }}/app:/var/www/html" + - "{{ services.nextcloud.volume_folder }}/app:/var/www/html" depends_on: - "postgres" - "redis" @@ -54,8 +54,8 @@ volumes: - "{{ services.nextcloud.volume_folder }}/app:/var/www/html" environment: - VIRTUAL_HOST: "{{ nextcloud.domain }}" - LETSENCRYPT_HOST: "{{ nextcloud.domain }}" + VIRTUAL_HOST: "{{ services.nextcloud.domain }}" + LETSENCRYPT_HOST: "{{ services.nextcloud.domain }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" POSTGRES_HOST: "postgres" POSTGRES_DB: "nextcloud" diff --git a/roles/docker/tasks/services/postfix.yml b/roles/docker/tasks/services/postfix.yml index 505842d..c565686 100644 --- a/roles/docker/tasks/services/postfix.yml +++ b/roles/docker/tasks/services/postfix.yml @@ -15,13 +15,6 @@ networks: - name: postfix env: - ALLOWED_SENDER_DOMAINS: "{{ allowed_sender_domains|join(' ') }}" + # Get all services which have allowed_sender_domain defined + ALLOWED_SENDER_DOMAINS: "{{ services | dict2items | selectattr('value.allowed_sender_domain', 'defined') | map(attribute='value.domain') | list | join(' ') }}" HOSTNAME: "smtp.data.coop" # the name the smtp server will identify itself as - vars: - allowed_sender_domains: - - "services.{{ base_domain }}" - - "{{ services.passit.domain }}" - - "{{ services.gitea.domain }}" - - "{{ services.mastodon.domain }}" - - "{{ services.rallly.domain }}" - - "{{ services.membersystem.domain }}" diff --git a/roles/docker/tasks/services/websites/2022.slides.data.coop.yml b/roles/docker/tasks/services/websites/2022.slides.data.coop.yml index 33124b1..260af82 100644 --- a/roles/docker/tasks/services/websites/2022.slides.data.coop.yml +++ b/roles/docker/tasks/services/websites/2022.slides.data.coop.yml @@ -9,8 +9,8 @@ networks: - name: external_services env: - VIRTUAL_HOST: "2022.slides.{{ data_coop_website.domains|join(',') }}" - LETSENCRYPT_HOST: "2022.slides.{{ data_coop_website.domains|join(',') }}" + VIRTUAL_HOST: "2022.slides.{{ services.data_coop_website.domains|join(',') }}" + LETSENCRYPT_HOST: "2022.slides.{{ services.data_coop_website.domains|join(',') }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" # Temporarily hosting on github command: "--remote=https://github.com/sorbusursina/datacoop-slides.git#slides2022" diff --git a/roles/docker/tasks/services/websites/cryptoaarhus.dk.yml b/roles/docker/tasks/services/websites/cryptoaarhus.dk.yml index 281cde8..28d6997 100644 --- a/roles/docker/tasks/services/websites/cryptoaarhus.dk.yml +++ b/roles/docker/tasks/services/websites/cryptoaarhus.dk.yml @@ -8,8 +8,8 @@ networks: - name: external_services env: - VIRTUAL_HOST : "{{ cryptoaarhus_website.domains|join(',') }}" - LETSENCRYPT_HOST: "{{ cryptoaarhus_website.domains|join(',') }}" + VIRTUAL_HOST : "{{ services.cryptoaarhus_website.domains|join(',') }}" + LETSENCRYPT_HOST: "{{ services.cryptoaarhus_website.domains|join(',') }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" labels: com.centurylinklabs.watchtower.enable: "true" diff --git a/roles/docker/tasks/services/websites/cryptohagen.dk.yml b/roles/docker/tasks/services/websites/cryptohagen.dk.yml index f9a2939..dcca218 100644 --- a/roles/docker/tasks/services/websites/cryptohagen.dk.yml +++ b/roles/docker/tasks/services/websites/cryptohagen.dk.yml @@ -8,8 +8,8 @@ networks: - name: external_services env: - VIRTUAL_HOST : "{{ cryptohagen_website.domains|join(',') }}" - LETSENCRYPT_HOST: "{{ cryptohagen_website.domains|join(',') }}" + VIRTUAL_HOST : "{{ services.cryptohagen_website.domains|join(',') }}" + LETSENCRYPT_HOST: "{{ services.cryptohagen_website.domains|join(',') }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" labels: com.centurylinklabs.watchtower.enable: "true" diff --git a/roles/docker/tasks/services/websites/data.coop.yml b/roles/docker/tasks/services/websites/data.coop.yml index 19e5536..2492757 100644 --- a/roles/docker/tasks/services/websites/data.coop.yml +++ b/roles/docker/tasks/services/websites/data.coop.yml @@ -8,8 +8,8 @@ networks: - name: external_services env: - VIRTUAL_HOST : "{{ data_coop_website.domains|join(',') }}" - LETSENCRYPT_HOST: "{{ data_coop_website.domains|join(',') }}" + VIRTUAL_HOST : "{{ services.data_coop_website.domains|join(',') }}" + LETSENCRYPT_HOST: "{{ services.data_coop_website.domains|join(',') }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" labels: com.centurylinklabs.watchtower.enable: "true" diff --git a/roles/docker/tasks/services/websites/new-new.data.coop.yml b/roles/docker/tasks/services/websites/new-new.data.coop.yml index 2119f2b..05ff1f3 100644 --- a/roles/docker/tasks/services/websites/new-new.data.coop.yml +++ b/roles/docker/tasks/services/websites/new-new.data.coop.yml @@ -7,8 +7,8 @@ networks: - name: external_services env: - VIRTUAL_HOST: "new-new.{{ data_coop_website.domains|join(',') }}" - LETSENCRYPT_HOST: "new-new.{{ data_coop_website.domains|join(',') }}" + VIRTUAL_HOST: "new-new.{{ services.data_coop_website.domains|join(',') }}" + LETSENCRYPT_HOST: "new-new.{{ services.data_coop_website.domains|join(',') }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" # The ssh-key is for read-only only command: "--remote=git@git.data.coop:halfd/new-website.git#main --ssh-key ed25519:Ag9RekCyC2eow4P/e5crVvSTQ7dTK46WkG0wqEPVJbU= --ssh-authenticator SHA256:l9kdLkb0kJm46pOJ4tCHCtFUaqV1ImbZWMA5oje10fI" diff --git a/roles/docker/tasks/services/websites/new.data.coop.yml b/roles/docker/tasks/services/websites/new.data.coop.yml index 404632c..f70596a 100644 --- a/roles/docker/tasks/services/websites/new.data.coop.yml +++ b/roles/docker/tasks/services/websites/new.data.coop.yml @@ -8,8 +8,8 @@ networks: - name: external_services env: - VIRTUAL_HOST : "new.{{ data_coop_website.domains|join(',') }}" - LETSENCRYPT_HOST: "new.{{ data_coop_website.domains|join(',') }}" + VIRTUAL_HOST : "new.{{ services.data_coop_website.domains|join(',') }}" + LETSENCRYPT_HOST: "new.{{ services.data_coop_website.domains|join(',') }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" labels: com.centurylinklabs.watchtower.enable: "true" diff --git a/roles/docker/tasks/services/websites/ulovliglogning.dk.yml b/roles/docker/tasks/services/websites/ulovliglogning.dk.yml index 0258df6..7abec88 100644 --- a/roles/docker/tasks/services/websites/ulovliglogning.dk.yml +++ b/roles/docker/tasks/services/websites/ulovliglogning.dk.yml @@ -6,8 +6,8 @@ networks: - name: external_services env: - VIRTUAL_HOST: "{{ ulovliglogning_website.domains|join(',') }}" - LETSENCRYPT_HOST: "{{ ulovliglogning_website.domains|join(',') }}" + VIRTUAL_HOST: "{{ services.ulovliglogning_website.domains|join(',') }}" + LETSENCRYPT_HOST: "{{ services.ulovliglogning_website.domains|join(',') }}" LETSENCRYPT_EMAIL: "{{ letsencrypt_email }}" labels: com.centurylinklabs.watchtower.enable: "true" diff --git a/roles/ubuntu_base/tasks/users.yml b/roles/ubuntu_base/tasks/users.yml index 010666e..deea339 100644 --- a/roles/ubuntu_base/tasks/users.yml +++ b/roles/ubuntu_base/tasks/users.yml @@ -9,14 +9,14 @@ loop: "{{ users | default([]) }}" - name: "Add ssh authorized_keys" - authorized_key: + ansible.posix.authorized_key: user: "{{ item.name }}" key: "{{ item.ssh_keys | join('\n') }}" exclusive: true loop: "{{ users | default([]) }}" - name: "Add ssh authorized_keys to root user" - authorized_key: + ansible.posix.authorized_key: user: "root" key: "{{ users | default([]) | map(attribute='ssh_keys') | flatten | join('\n') }}" exclusive: true