diff --git a/group_vars/all b/group_vars/all new file mode 100644 index 0000000..a47a9a4 --- /dev/null +++ b/group_vars/all @@ -0,0 +1 @@ +snmpd_conf: /etc/snmp/snmpd.conf \ No newline at end of file diff --git a/host_vars/mewimeet.de.yml b/host_vars/mewimeet.de.yml index 5b673bb..9a23a8c 100644 --- a/host_vars/mewimeet.de.yml +++ b/host_vars/mewimeet.de.yml @@ -19,6 +19,8 @@ set_hosts: true unattended_upgrades: true web_server: true netdata: true +bind: true +unbound: true # VPN wireguard: true diff --git a/hosts b/hosts index cad0a73..09200e2 100644 --- a/hosts +++ b/hosts @@ -40,6 +40,7 @@ tuxedo-book-xp1511.universe.local [nameserver] coruscant.universe.local +mewimeet.de [photo_editing] endor.universe.local diff --git a/local.yml b/local.yml index 7b02b55..5f5fdc1 100644 --- a/local.yml +++ b/local.yml @@ -3,6 +3,8 @@ handlers: - import_tasks: global_handlers/global_handlers.yml connection: local + vars_files: + - "os_vars/{{ ansible_distribution | lower }}.yml" become: true pre_tasks: @@ -72,6 +74,12 @@ # roles: # - fileserver +- hosts: mastodon + tags: server,mastodon + become: true + roles: + - mastodon + - hosts: nameserver tags: server,nameserver become: true diff --git a/os_vars/debian.yml b/os_vars/debian.yml index fc36047..baad885 100644 --- a/os_vars/debian.yml +++ b/os_vars/debian.yml @@ -1,11 +1,11 @@ snmp-user: Debian-snmp -redis: +redis_pkgs: packages: - package: "redis-server" - package: "redis-tools" -postgres: +postgres_pkgs: packages: - package: "libpq-dev" - package: "postgresql" diff --git a/os_vars/ubuntu.yml b/os_vars/ubuntu.yml index fc36047..baad885 100644 --- a/os_vars/ubuntu.yml +++ b/os_vars/ubuntu.yml @@ -1,11 +1,11 @@ snmp-user: Debian-snmp -redis: +redis_pkgs: packages: - package: "redis-server" - package: "redis-tools" -postgres: +postgres_pkgs: packages: - package: "libpq-dev" - package: "postgresql" diff --git a/roles/database/tasks/configure_snmpd.yml b/roles/database/tasks/configure_snmpd.yml new file mode 100644 index 0000000..a260fba --- /dev/null +++ b/roles/database/tasks/configure_snmpd.yml @@ -0,0 +1,61 @@ +- name: database | snmpd | get script + get_url: + url: "https://github.com/librenms/librenms-agent/raw/master/snmp/postgres" + dest: "/etc/snmp/postgres" + mode: "0755" + owner: "root" + group: "root" + when: postgres == true + register: postgres_script + +- name: database | snmpd | modify script part 1 + lineinfile: + path: "/etc/snmp/postgres" + regexp: "^\$cpg -u $DBuser --action dbstats | awk -F ' ' '$" + state: present + line: "$cpg --action dbstats | awk -F ' ' '" + when: postgres_script.rc == 0 + +- name: database | snmpd | modify script part 2 + replace: + path: "/etc/snmp/postgres" + regexp: "\\:" + replace: ":" + when: postgres_script.rc == 0 + +- include_tasks: install_check_postgres.yml + when: postgres == true + +- name: database | snmpd | get script + get_url: + url: "https://github.com/librenms/librenms-agent/raw/master/snmp/mysql" + dest: "/etc/snmp/mysql" + mode: "0755" + owner: "root" + group: "root" + when: mysql == true + +- name: database | snmpd | create configuration + template: + src: "mysql.cnf.j2" + dest: "/etc/snmp/mysql.cnf" + mode: "0644" + when: mysql == true + +- name: database | snmpd | configure extend + lineinfile: + path: "{{ snmpd_conf }}" + state: present + line: "extend postgres /usr/bin/sudo -u postgres /etc/snmp/postgres" + insertafter: "# SECTION: Extends" + notify: restart_snmpd + when: postgres == true + +- name: database | snmpd | configure extend + lineinfile: + path: "{{ snmpd_conf }}" + state: present + line: "extend mysql /etc/snmp/mysql" + insertafter: "# SECTION: Extends" + notify: restart_snmpd + when: mysql == true \ No newline at end of file diff --git a/roles/database/tasks/install_check_postgres.yml b/roles/database/tasks/install_check_postgres.yml new file mode 100644 index 0000000..531da27 --- /dev/null +++ b/roles/database/tasks/install_check_postgres.yml @@ -0,0 +1,23 @@ +- name: database | snmpd | get script + git: + repo: "https://github.com/bucardo/check_postgres.git" + dest: "~/check_postgres" + +- name: database | snmpd | prepare script + command: + cmd: "perl Makefile.PL" + creates: "~/check_postgres/Makefile" + chdir: "~/check_postgres" + +- name: database | snmpd | build script + command: + cmd: "make" + chdir: "~/check_postgres" + creates: "~/check_postgres/pm_to_blib" + +- name: database | snmpd | install script + command: + cmd: "make install" + chdir: "~/check_postgres" + creates: "/usr/local/bin/check_postgres.pl" + become: true diff --git a/roles/database/tasks/install_mysql.yml b/roles/database/tasks/install_mysql.yml new file mode 100644 index 0000000..d972aaf --- /dev/null +++ b/roles/database/tasks/install_mysql.yml @@ -0,0 +1,2 @@ +- debug: + msg: "mysql: {{ mysql }}" \ No newline at end of file diff --git a/roles/database/tasks/install_postgres.yml b/roles/database/tasks/install_postgres.yml new file mode 100644 index 0000000..0d82df0 --- /dev/null +++ b/roles/database/tasks/install_postgres.yml @@ -0,0 +1,9 @@ +- name: database | postgres | install postgres packages + package: + name: "{{ item.package }}" + update_cache: yes + cache_valid_time: 3600 + state: latest + install_recommends: no + become: yes + with_items: "{{ postgres_pkgs.packages }}" \ No newline at end of file diff --git a/roles/database/tasks/install_redis.yml b/roles/database/tasks/install_redis.yml new file mode 100644 index 0000000..cd27d50 --- /dev/null +++ b/roles/database/tasks/install_redis.yml @@ -0,0 +1,9 @@ +- name: database | redis | install redis packages + package: + name: "{{ item.package }}" + update_cache: yes + cache_valid_time: 3600 + state: latest + install_recommends: no + become: yes + with_items: "{{ redis_pkgs.packages }}" \ No newline at end of file diff --git a/roles/database/tasks/main.yml b/roles/database/tasks/main.yml new file mode 100644 index 0000000..0b6d41c --- /dev/null +++ b/roles/database/tasks/main.yml @@ -0,0 +1,17 @@ +# Load distro-specific variables +- include_vars: "{{ ansible_distribution|lower }}.yml" + tags: always + ignore_errors: True + +- block: + - debug: + msg: "mysql: {{ mysql }}" + # install software + - import_tasks: install_mysql.yml + when: + - mysql is defined + - mysql == true + - import_tasks: install_postgres.yml + when: postgres == true + - import_tasks: install_redis.yml + when: redis == true \ No newline at end of file diff --git a/roles/database/vars/debian.yml b/roles/database/vars/debian.yml new file mode 100644 index 0000000..1f75b2f --- /dev/null +++ b/roles/database/vars/debian.yml @@ -0,0 +1,12 @@ +redis_pkgs: + packages: + - package: "redis-server" + - package: "redis-tools" + +postgres_pkgs: + packages: + - package: "libpq-dev" + - package: "postgresql" + - package: "postgresql-contrib" + - package: "python3-psycopg2" + - package: "sudo" \ No newline at end of file diff --git a/roles/database/vars/ubuntu.yml b/roles/database/vars/ubuntu.yml new file mode 100644 index 0000000..1f75b2f --- /dev/null +++ b/roles/database/vars/ubuntu.yml @@ -0,0 +1,12 @@ +redis_pkgs: + packages: + - package: "redis-server" + - package: "redis-tools" + +postgres_pkgs: + packages: + - package: "libpq-dev" + - package: "postgresql" + - package: "postgresql-contrib" + - package: "python3-psycopg2" + - package: "sudo" \ No newline at end of file diff --git a/roles/mastodon/tasks/main.yml b/roles/mastodon/tasks/main.yml new file mode 100644 index 0000000..a8564dd --- /dev/null +++ b/roles/mastodon/tasks/main.yml @@ -0,0 +1,21 @@ +--- +# Load distro specific variables +- include_vars: "{{ ansible_distribution }}.yml" + tags: always +- include_vars: "{{ ansible_fqdn }}.yml" + ignore_errors: True + +- include_tasks: system_setup/prepare_packagemanager.yml + +- block: + - include_role: name=database + - include_tasks: system_setup/prepare_database.yml + - include_role: name=webserver + - include_tasks: system_setup/packages.yml + - include_tasks: system_setup/nginx.yml + - include_tasks: system_setup/user.yml + - include_tasks: system_setup/ruby.yml + - include_tasks: system_setup/mastodon.yml + - include_tasks: system_setup/letsencrypt.yml + rescue: + - set_fact: task_failed=true \ No newline at end of file diff --git a/roles/mastodon/tasks/system_setup/letsencrypt.yml b/roles/mastodon/tasks/system_setup/letsencrypt.yml new file mode 100644 index 0000000..a95574e --- /dev/null +++ b/roles/mastodon/tasks/system_setup/letsencrypt.yml @@ -0,0 +1,29 @@ +--- +- stat: path=/etc/letsencrypt/live/{{ mastodon_host | default(ansible_fqdn) }}/fullchain.pem + register: letsencrypt_cert + +- name: Copy letsencrypt nginx config + template: + src: mastodon.conf.j2 + dest: /etc/nginx/sites-available/mastodon.conf + +- name: Symlink enabled site + file: + src: "/etc/nginx/sites-available/mastodon.conf" + dest: "/etc/nginx/sites-enabled/mastodon.conf" + state: link + +- name: Reload nginx + command: "systemctl reload nginx" + +- name: Install letsencrypt cert + command: letsencrypt certonly -n --webroot -d {{ mastodon_host | default(ansible_fqdn) }} -w {{ mastodon_home }}/{{ mastodon_path }}/public/ --email "webmaster@{{ mastodon_host | default(ansible_fqdn) }}" --agree-tos && systemctl reload nginx + when: not letsencrypt_cert.stat.exists + +- name: Letsencrypt Job + cron: + name: "letsencrypt renew" + minute: "15" + hour: "0" + job: "letsencrypt renew && service nginx reload" + diff --git a/roles/mastodon/tasks/system_setup/mastodon.yml b/roles/mastodon/tasks/system_setup/mastodon.yml new file mode 100644 index 0000000..eb8835d --- /dev/null +++ b/roles/mastodon/tasks/system_setup/mastodon.yml @@ -0,0 +1,86 @@ +- block: + - name: Clone mastodon + git: + repo: "https://github.com/mastodon/mastodon.git" + dest: "{{ mastodon_home }}/{{mastodon_path}}" + clone: true + + # - name: Update to latest version + # shell: "git fetch; git checkout $(git tag -l | grep -v 'rc[1-9]*$' | sort -V | tail -n 1)" + # args: + # chdir: "{{ mastodon_home }}/{{ mastodon_path }}" + + - name: Bundle install + shell: | + ~/.rbenv/shims/bundle config set --local deployment 'true' && \ + ~/.rbenv/shims/bundle config set --local without 'test' && \ + ~/.rbenv/shims/bundle config set --local with 'development' && \ + ~/.rbenv/shims/bundle install -j$(getconf _NPROCESSORS_ONLN) + args: + chdir: "{{ mastodon_home }}/{{ mastodon_path }}" + + - name: Yarn install + command: yarn install --pure-lockfile + args: + chdir: "{{ mastodon_home }}/{{ mastodon_path }}" + + - name: Media cleanup cronjob + cron: + name: "media cleanup" + minute: "15" + hour: "1" + job: '/bin/bash -c ''export PATH="$HOME/.rbenv/bin:$PATH"; eval "$(rbenv init -)"; cd {{ mastodon_home }}/{{ mastodon_path }} && RAILS_ENV=production ./bin/tootctl media remove''' + + - stat: path={{ mastodon_home }}/{{ mastodon_path }}/.env.production + register: production_config + + - name: Migrate database + shell: "RAILS_ENV=production ~/.rbenv/shims/bundle exec rails db:migrate" + args: + chdir: "{{ mastodon_home }}/{{ mastodon_path }}" + when: production_config.stat.exists + + - name: Precompile assets + shell: "RAILS_ENV=production ~/.rbenv/shims/bundle exec rails assets:precompile" + args: + chdir: "{{ mastodon_home }}/{{ mastodon_path }}" + when: production_config.stat.exists + + become: true + become_user: "{{ mastodon_user }}" + +- name: Install systemd sidekiq Service Files + template: + src: mastodon-sidekiq.service.j2 + dest: /etc/systemd/system/mastodon-sidekiq.service + +- name: Install systemd web Service Files + template: + src: mastodon-web.service.j2 + dest: /etc/systemd/system/mastodon-web.service + +- name: Install systemd streaming Service Files + template: + src: mastodon-streaming.service.j2 + dest: /etc/systemd/system/mastodon-streaming.service + +- name: Enable mastodon-web + command: systemctl enable mastodon-web.service + +- name: Enable mastodon-streaming + command: systemctl enable mastodon-streaming.service + +- name: Enable mastodon-sidekiq + command: systemctl enable mastodon-sidekiq.service + +- name: Restart mastodon-web + command: systemctl restart mastodon-web.service + when: production_config.stat.exists + +- name: Restart mastodon-streaming + command: systemctl restart mastodon-streaming.service + when: production_config.stat.exists + +- name: Restart mastodon-sidekiq + command: systemctl restart mastodon-sidekiq.service + when: production_config.stat.exists \ No newline at end of file diff --git a/roles/mastodon/tasks/system_setup/nginx.yml b/roles/mastodon/tasks/system_setup/nginx.yml new file mode 100644 index 0000000..f3d2a18 --- /dev/null +++ b/roles/mastodon/tasks/system_setup/nginx.yml @@ -0,0 +1,16 @@ +--- +- debug: + msg: "Hostname: {{ mastodon_host | default(ansible_fqdn) }}" + +- name: mastodon | Copy nginx config + template: + src: mastodon.conf.j2 + dest: /etc/nginx/sites-available/mastodon.conf + notify: restart_nginx + +- name: mastodon | Symlink enabled site + file: + src: "/etc/nginx/sites-available/mastodon.conf" + dest: "/etc/nginx/sites-enabled/mastodon.conf" + state: link + notify: restart_nginx \ No newline at end of file diff --git a/roles/mastodon/tasks/system_setup/packages.yml b/roles/mastodon/tasks/system_setup/packages.yml new file mode 100644 index 0000000..efccfa5 --- /dev/null +++ b/roles/mastodon/tasks/system_setup/packages.yml @@ -0,0 +1,16 @@ +--- + +- name: mastodon | Install packages + package: + name: "{{ item.package }}" + update_cache: yes + cache_valid_time: 3600 + state: latest + install_recommends: no + with_items: "{{ packages }}" + +- name: mastodon | nodejs alternative + alternatives: + name: node + path: /usr/bin/node + link: /usr/bin/nodejs \ No newline at end of file diff --git a/roles/mastodon/tasks/system_setup/prepare_database.yml b/roles/mastodon/tasks/system_setup/prepare_database.yml new file mode 100644 index 0000000..ee7e79f --- /dev/null +++ b/roles/mastodon/tasks/system_setup/prepare_database.yml @@ -0,0 +1,51 @@ +- name: mastodon | postgres | Create database {{ mastodon_db }} + postgresql_db: + name: "{{ mastodon_db }}" + login_host: "{{ mastodon_db_login_host }}" + login_password: "{{ mastodon_db_login_password }}" + login_user: "{{ mastodon_db_login_user }}" + port: "{{ mastodon_db_port }}" + register: create_remote_db + when: + - mastodon_db_login_user is defined + - mastodon_db_login_host is defined + - mastodon_db_login_password is defined + - mastodon_db_port is defined + +- name: mastodon | postgres | Create database user {{ mastodon_db_user }} + postgresql_user: + db: "{{ mastodon_db }}" + name: "{{ mastodon_db_user }}" + password: "{{ mastodon_db_password }}" + login_host: "{{ mastodon_db_login_host }}" + login_password: "{{ mastodon_db_login_password }}" + login_user: "{{ mastodon_db_login_user }}" + port: "{{ mastodon_db_port }}" + role_attr_flags: CREATEDB + register: create_remote_db_user + when: + - mastodon_db_login_user is defined + - mastodon_db_login_host is defined + - mastodon_db_login_password is defined + - mastodon_db_port is defined + +- name: mastodon | postgres | Create database {{ mastodon_db }} + postgresql_db: + name: "{{ mastodon_db }}" + login_unix_socket: "{{ mastodon_db_login_unix_socket }}" + register: create_local_db + become: true + become_user: "postgres" + when: create_remote_db is skipped + +- name: mastodon | postgres | Create database user {{ mastodon_db_user }} + postgresql_user: + db: "{{ mastodon_db }}" + name: "{{ mastodon_db_user }}" + password: "{{ mastodon_db_password | default('') }}" + encrypted: yes + login_unix_socket: "{{ mastodon_db_login_unix_socket }}" + role_attr_flags: CREATEDB + become: true + become_user: "postgres" + when: create_remote_db_user is skipped \ No newline at end of file diff --git a/roles/mastodon/tasks/system_setup/prepare_packagemanager.yml b/roles/mastodon/tasks/system_setup/prepare_packagemanager.yml new file mode 100644 index 0000000..ae018b4 --- /dev/null +++ b/roles/mastodon/tasks/system_setup/prepare_packagemanager.yml @@ -0,0 +1,20 @@ +- name: mastodon | package manager | add gpg keys + apt_key: + id: "{{ item.id }}" + url: "{{ item.url }}" + state: present + loop: + - { id: "72ECF46A56B4AD39C907BBB71646B01B86E50310", url: "https://dl.yarnpkg.com/debian/pubkey.gpg" } + - { id: "9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280", url: "https://deb.nodesource.com/gpgkey/nodesource.gpg.key" } + +- name: mastodon | package manager | add repos + apt_repository: + repo: "{{ item.repo }}" + state: present + mode: 0644 # not required. The octal mode for newly created files in sources.list.d + update_cache: no + validate_certs: yes # not required. If C(no), SSL certificates for the target repo will not be validated. This should only be used on personally controlled sites using self-signed certificates. + filename: "{{ item.filename }}" + loop: + - { repo: "deb https://dl.yarnpkg.com/debian/ stable main", filename: "yarn"} + - { repo: "deb https://deb.nodesource.com/node_{{ node_major_version }}.x {{ ansible_lsb.codename }} main", filename: "nodejs"} \ No newline at end of file diff --git a/roles/mastodon/tasks/system_setup/ruby.yml b/roles/mastodon/tasks/system_setup/ruby.yml new file mode 100644 index 0000000..0ad29e7 --- /dev/null +++ b/roles/mastodon/tasks/system_setup/ruby.yml @@ -0,0 +1,62 @@ +--- +- block: + - name: mastodon | Clone rbenv + git: + repo: "https://github.com/rbenv/rbenv.git" + dest: "~/.rbenv" + clone: true + version: "{{ rbenv_version }}" + + - name: mastodon | Clone ruby-build + git: + repo: "https://github.com/rbenv/ruby-build.git" + dest: "~/.rbenv/plugins/ruby-build" + clone: true + version: "{{ ruby_build_version }}" + register: ruby_build + + - name: mastodon | Configure rbenv + command: ./configure + args: + chdir: "~/.rbenv/src" + register: rbenv_configure + + - name: mastodon | Build rbenv + command: make + args: + chdir: "~/.rbenv/src" + when: rbenv_configure is succeeded + + - name: mastodon | Update profile settings + blockinfile: + dest: "~/.profile" + content: | + export PATH="~/.rbenv/bin:${PATH}" + eval "$(rbenv init -)" + + - name: mastodon | Check if the Ruby version is already installed + shell: "~/.rbenv/bin/rbenv versions | grep -q {{ ruby_version }}" + register: ruby_installed + ignore_errors: yes + check_mode: no + + - name: mastodon | Install Ruby {{ ruby_version }} + shell: "~/.rbenv/bin/rbenv install {{ ruby_version }}" + args: + executable: /bin/bash + when: ruby_installed is failed + + - name: mastodon | Set the default Ruby version to {{ ruby_version }} + shell: "~/.rbenv/bin/rbenv global {{ ruby_version }}" + args: + executable: /bin/bash + register: default_ruby_version + + - name: mastodon | Install bundler + shell: 'export PATH="$HOME/.rbenv/bin:$PATH"; eval "$(rbenv init -)"; gem install bundler:{{ bundler_version }}' + args: + executable: /bin/bash + when: default_ruby_version is succeeded + + become: true + become_user: "{{ mastodon_user }}" \ No newline at end of file diff --git a/roles/mastodon/tasks/system_setup/user.yml b/roles/mastodon/tasks/system_setup/user.yml new file mode 100644 index 0000000..28d9676 --- /dev/null +++ b/roles/mastodon/tasks/system_setup/user.yml @@ -0,0 +1,6 @@ +- name: mastodon | create mastodon user + user: + name: "{{ mastodon_user }}" + createhome: true + shell: /bin/bash + home: "{{ mastodon_home }}" \ No newline at end of file diff --git a/roles/mastodon/templates/letsencrypt.conf.j2 b/roles/mastodon/templates/letsencrypt.conf.j2 new file mode 100644 index 0000000..d496a89 --- /dev/null +++ b/roles/mastodon/templates/letsencrypt.conf.j2 @@ -0,0 +1,8 @@ +# This starts a simple nginx for the letsencrypt acme challenge +server { + listen 80; + listen [::]:80; + server_name {{ mastodon_host }}; + root {{ mastodon_home }}/{{ mastodon_path }}/public; + location /.well-known/acme-challenge/ { allow all; } +} \ No newline at end of file diff --git a/roles/mastodon/templates/mastodon-sidekiq.service.j2 b/roles/mastodon/templates/mastodon-sidekiq.service.j2 new file mode 100644 index 0000000..466297e --- /dev/null +++ b/roles/mastodon/templates/mastodon-sidekiq.service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=mastodon-sidekiq +After=network.target + +[Service] +Type=simple +User=mastodon +WorkingDirectory={{ mastodon_home }}/{{ mastodon_path }} +Environment="RAILS_ENV=production" +Environment="DB_POOL=5" +ExecStart={{ mastodon_home }}/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q push -q mailers -q pull +TimeoutSec=15 +Restart=always + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/roles/mastodon/templates/mastodon-streaming.service.j2 b/roles/mastodon/templates/mastodon-streaming.service.j2 new file mode 100644 index 0000000..cf2a8ff --- /dev/null +++ b/roles/mastodon/templates/mastodon-streaming.service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=mastodon-streaming +After=network.target + +[Service] +Type=simple +User=mastodon +WorkingDirectory={{ mastodon_home }}/{{ mastodon_path }} +Environment="NODE_ENV=production" +Environment="PORT=4000" +ExecStart=/usr/bin/npm run start +TimeoutSec=15 +Restart=always + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/roles/mastodon/templates/mastodon-web.service.j2 b/roles/mastodon/templates/mastodon-web.service.j2 new file mode 100644 index 0000000..747684f --- /dev/null +++ b/roles/mastodon/templates/mastodon-web.service.j2 @@ -0,0 +1,17 @@ +[Unit] +Description=mastodon-web +After=network.target + +[Service] +Type=simple +User=mastodon +WorkingDirectory={{ mastodon_home }}/{{ mastodon_path }} +Environment="RAILS_ENV=production" +Environment="PORT=3000" +ExecStart={{ mastodon_home }}/.rbenv/shims/bundle exec puma -C config/puma.rb +ExecReload=/bin/kill -SIGUSR1 $MAINPID +TimeoutSec=15 +Restart=always + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/roles/mastodon/templates/mastodon.conf.j2 b/roles/mastodon/templates/mastodon.conf.j2 new file mode 100644 index 0000000..234534b --- /dev/null +++ b/roles/mastodon/templates/mastodon.conf.j2 @@ -0,0 +1,100 @@ +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + listen [::]:80; + server_name {{ mastodon_host | default(ansible_fqdn) }}; + + # Useful for Let's Encrypt + location /.well-known/acme-challenge/ { allow all; } + location / { return 301 https://$host$request_uri; } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name {{ mastodon_host | default(ansible_fqdn) }}; + + ssl_protocols TLSv1.2; + ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + +{% if disable_letsencrypt != "true" %} + ssl_certificate /etc/letsencrypt/live/{{ mastodon_host | default(ansible_fqdn) }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ mastodon_host | default(ansible_fqdn) }}/privkey.pem; +{% endif %} + + keepalive_timeout 70; + sendfile on; + client_max_body_size 8m; + + root {{ mastodon_home }}/{{ mastodon_path }}/public; + + gzip on; + gzip_disable "msie6"; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + +{% if disable_hsts == "true" %} + add_header Strict-Transport-Security "max-age=31536000"; +{% endif %} + + location / { + try_files $uri @proxy; + } + + location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) { + add_header Cache-Control "public, max-age=31536000, immutable"; + try_files $uri @proxy; + } + + location /sw.js { + add_header Cache-Control "public, max-age=0"; + try_files $uri @proxy; + } + + location @proxy { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Proxy ""; + proxy_pass_header Server; + + proxy_pass http://127.0.0.1:3000; + proxy_buffering off; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + tcp_nodelay on; + } + + location /api/v1/streaming { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Proxy ""; + + proxy_pass http://127.0.0.1:4000; + proxy_buffering off; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + tcp_nodelay on; + } + + error_page 500 501 502 503 504 /500.html; +} \ No newline at end of file diff --git a/roles/mastodon/vars/Debian.yml b/roles/mastodon/vars/Debian.yml new file mode 100644 index 0000000..da091ae --- /dev/null +++ b/roles/mastodon/vars/Debian.yml @@ -0,0 +1,33 @@ +mastodon_db_login_unix_socket: '/var/run/postgresql' + +packages: + - package: "autoconf" + - package: "bison" + - package: "build-essential" + - package: "curl" + - package: "cron" + - package: "ffmpeg" + - package: "file" + - package: "g++" + - package: "gcc" + - package: "git" + - package: "imagemagick" + - package: "libffi-dev" + - package: "libgdbm-dev" + - package: "libicu-dev" + - package: "libidn11-dev" + - package: "libncurses5-dev" + - package: "libpq-dev" + - package: "libprotobuf-dev" + - package: "libreadline-dev" + - package: "libssl-dev" + - package: "libxml2-dev" + - package: "libxslt1-dev" + - package: "libyaml-dev" + - package: "nodejs" + - package: "pkg-config" + - package: "protobuf-compiler" + - package: "sudo" + - package: "systemd" + - package: "yarn" + - package: "zlib1g-dev" \ No newline at end of file diff --git a/roles/mastodon/vars/Ubuntu.yml b/roles/mastodon/vars/Ubuntu.yml new file mode 100644 index 0000000..da091ae --- /dev/null +++ b/roles/mastodon/vars/Ubuntu.yml @@ -0,0 +1,33 @@ +mastodon_db_login_unix_socket: '/var/run/postgresql' + +packages: + - package: "autoconf" + - package: "bison" + - package: "build-essential" + - package: "curl" + - package: "cron" + - package: "ffmpeg" + - package: "file" + - package: "g++" + - package: "gcc" + - package: "git" + - package: "imagemagick" + - package: "libffi-dev" + - package: "libgdbm-dev" + - package: "libicu-dev" + - package: "libidn11-dev" + - package: "libncurses5-dev" + - package: "libpq-dev" + - package: "libprotobuf-dev" + - package: "libreadline-dev" + - package: "libssl-dev" + - package: "libxml2-dev" + - package: "libxslt1-dev" + - package: "libyaml-dev" + - package: "nodejs" + - package: "pkg-config" + - package: "protobuf-compiler" + - package: "sudo" + - package: "systemd" + - package: "yarn" + - package: "zlib1g-dev" \ No newline at end of file diff --git a/roles/mastodon/vars/main.yml b/roles/mastodon/vars/main.yml new file mode 100644 index 0000000..e3c141e --- /dev/null +++ b/roles/mastodon/vars/main.yml @@ -0,0 +1,21 @@ +webserver: True +nginx: True +database: True +postgres: True +mysql: False +redis: True + +ruby_version: "3.0.3" +rbenv_version: "v1.2.0" +ruby_build_version: "v20220218" +bundler_version: "2.1.4" +node_major_version: "12" +os_family: "{{ ansible_os_family|lower }}" +mastodon_user: "mastodon" +mastodon_home: "/home/{{ mastodon_user }}" +mastodon_db_user: "{{ mastodon_user }}" +mastodon_path: "live" +mastodon_db: "{{ mastodon_user }}_development" +mastodon_db_port: 5432 +disable_hsts: "false" +disable_letsencrypt: "false" \ No newline at end of file diff --git a/roles/nameserver/handlers/main.yml b/roles/nameserver/handlers/main.yml index 54ddee6..0c1fa07 100644 --- a/roles/nameserver/handlers/main.yml +++ b/roles/nameserver/handlers/main.yml @@ -6,4 +6,9 @@ - name: restart_snmpd service: name: "snmpd" + state: restarted + +- name: restart_unbound + service: + name: "unbound" state: restarted \ No newline at end of file diff --git a/roles/nameserver/tasks/configure_snmpd.yml b/roles/nameserver/tasks/configure_bind_snmpd.yml similarity index 76% rename from roles/nameserver/tasks/configure_snmpd.yml rename to roles/nameserver/tasks/configure_bind_snmpd.yml index 7c7587c..3c3a89f 100644 --- a/roles/nameserver/tasks/configure_snmpd.yml +++ b/roles/nameserver/tasks/configure_bind_snmpd.yml @@ -28,16 +28,16 @@ - name: nameserver | snmpd | configure named for statistics lineinfile: - path: "/etc/bind/named.conf.options" # required. The file to modify. Before Ansible 2.3 this option was only usable as I(dest), I(destfile) and I(name). + path: "{{ named_conf_options }}" # required. The file to modify. Before Ansible 2.3 this option was only usable as I(dest), I(destfile) and I(name). state: present - line: "statistics-file "/var/cache/bind/stats"; zone-statistics yes;" + line: '\tstatistics-file "/var/cache/bind/stats";\n\tzone-statistics yes;' insertafter: "options {" - validate: /usr/bin/named-checkconf %s + validate: /usr/sbin/named-checkconf %s notify: restart_named - name: nameserver | snmpd | configure extend lineinfile: - path: "/etc/snmp/snmpd.conf" + path: "{{ snmpd_conf }}" state: present line: "extend bind /etc/snmp/bind" insertafter: "# SECTION: Extends" diff --git a/roles/nameserver/tasks/configure_unbound_snmpd.yml b/roles/nameserver/tasks/configure_unbound_snmpd.yml new file mode 100644 index 0000000..cbb0dbc --- /dev/null +++ b/roles/nameserver/tasks/configure_unbound_snmpd.yml @@ -0,0 +1,15 @@ +- name: nameserver | snmpd | get script + get_url: + url: "https://github.com/librenms/librenms-agent/raw/master/snmp/unbound" + dest: "/etc/snmp/unbound" + mode: "0755" + owner: "root" + group: "root" + +- name: nameserver | snmpd | configure extend + lineinfile: + path: "{{ snmpd_conf }}" + state: present + line: "extend unbound /usr/bin/sudo /etc/snmp/unbound" + insertafter: "# SECTION: Extends" + notify: restart_snmpd \ No newline at end of file diff --git a/roles/nameserver/tasks/disable-systemd-resolved.yml b/roles/nameserver/tasks/disable-systemd-resolved.yml new file mode 100644 index 0000000..9813bee --- /dev/null +++ b/roles/nameserver/tasks/disable-systemd-resolved.yml @@ -0,0 +1,23 @@ +- name: nameserver | systemd-resolved | edit config + lineinfile: + path: "/etc/systemd/resolved.conf" + regexp: "^.*DNSStubListener=.*$" + state: present + line: "DNSStubListener=no" + +- name: nameserver | systemd-resolved | stop and disable service + service: + name: "systemd-resolved" + state: stopped + enabled: false + +- name: nameserver | systemd-resolved | remove /etc/resolv.conf (symlink) + file: + path: "/etc/resolv.conf" + state: absent + +- name: nameserver | systemd-resolved | create new /etc/resolv.conf + copy: + dest: "/etc/resolv.conf" + content: | + nameserver 127.0.0.1 diff --git a/roles/nameserver/tasks/install_bind.yml b/roles/nameserver/tasks/install_bind.yml index bbf12d2..7309d9f 100644 --- a/roles/nameserver/tasks/install_bind.yml +++ b/roles/nameserver/tasks/install_bind.yml @@ -1,4 +1,24 @@ -- name: nameserver | install packages +- name: nameserver | bind | install packages package: name: "{{ bind_package }}" - state: present \ No newline at end of file + state: present + +- name: nameserver | bind | basic configuration + replace: + path: "{{ named_conf_options }}" + regexp: "{{ item.regexp }}" + replace: "{{ item.option }}" + validate: "{{ named_checkconf }} %s" + loop: + - { regexp: '^\s*listen-on \{(?:[\s\n]*(?:\d{1,3}\.){3}\d{1,3};)*[\s\n]*\};', option: "\tlisten-on { {{ ansible_default_ipv4.address }}; };"} + - { regexp: '^\s*listen-on-v6 \{[\s\n]*any;[\s\n]*\};', option: "\tlisten-on-v6 { {{ ansible_default_ipv6.address }}; };"} + - { regexp: '^\s*listen-on-v6 \{(?:[\s\n]*[\da-z:]*;)[\s\n]*\};', option: "\tlisten-on-v6 { {{ ansible_default_ipv6.address }}; };"} + +- name: nameserver | bind | basic configuration cont'd + lineinfile: + path: "{{ named_conf_options }}" + regexp: '^\s*listen-on \{.*\};' + state: present + line: "\tlisten-on { {{ ansible_default_ipv4.address }}; };" + insertafter: "options {" + validate: "{{ named_checkconf }} %s" \ No newline at end of file diff --git a/roles/nameserver/tasks/install_unbound.yml b/roles/nameserver/tasks/install_unbound.yml new file mode 100644 index 0000000..aa5ab6a --- /dev/null +++ b/roles/nameserver/tasks/install_unbound.yml @@ -0,0 +1,14 @@ +- name: nameserver | unbound | install packages + package: + name: "{{ unbound_package }}" + state: present + +- name: nameserver | unbound | copy config + template: + src: "unbound_network.conf.j2" + dest: "/etc/unbound/unbound.conf.d/network.conf" + mode: "0644" + owner: "root" + group: "root" + verify: "unbound-checkconf /etc/unbound/unbound.conf.d/network.conf" + notify: restart_unbound \ No newline at end of file diff --git a/roles/nameserver/tasks/main.yml b/roles/nameserver/tasks/main.yml index bb124dd..a3291a3 100644 --- a/roles/nameserver/tasks/main.yml +++ b/roles/nameserver/tasks/main.yml @@ -3,15 +3,24 @@ tags: always - block: - - debug: - msg: Debug + - name: nameserver | unbound | disable systemd-resolved + include_tasks: disable-systemd-resolved.yml + when: bind == true or unbound == true - # # import role - # - import_role: - # name: # required. The name of the role to be executed. + - block: + - include_tasks: install_bind.yml + - include_tasks: configure_bind_snmpd.yml + rescue: + - set_fact: task_failed=true + notify: restart_named + when: bind == true - # install software - - include_tasks: install_bind.yml + - block: + - include_tasks: install_unbound.yml + - include_tasks: configure_unbound_snmpd.yml + rescue: + - set_fact: task_failed=true + when: unbound == true rescue: - set_fact: task_failed=true \ No newline at end of file diff --git a/roles/nameserver/templates/unbound_network.conf.j2 b/roles/nameserver/templates/unbound_network.conf.j2 new file mode 100644 index 0000000..0681c6b --- /dev/null +++ b/roles/nameserver/templates/unbound_network.conf.j2 @@ -0,0 +1,17 @@ +server: + ip-freebind: yes + interface: {{ wg_local_ip | ipaddr('address') }} + interface: 127.0.0.1 + interface: 127.0.0.53 + interface: ::1 + outgoing-interface: {{ ansible_default_ipv4.address }} + outgoing-interface: {{ ansible_default_ipv6.address }} + access-control: 192.168.1.0/24 allow + access-control: 192.168.3.0/24 allow + access-control: 172.16.0.0/24 allow + extended-statistics: yes + statistics-cumulative: yes + +remote-control: + control-enable: yes + control-interface: 127.0.0.1 \ No newline at end of file diff --git a/roles/nameserver/vars/Archlinux.yml b/roles/nameserver/vars/Archlinux.yml index 81ec7ed..144d56c 100644 --- a/roles/nameserver/vars/Archlinux.yml +++ b/roles/nameserver/vars/Archlinux.yml @@ -1,2 +1,9 @@ bind_package: bind -perl_readbackwards: perl-file-readbackwards \ No newline at end of file +unbound_package: unbound +perl_readbackwards: perl-file-readbackwards + +# named / bind specific +named_conf_zones: /etc/named.conf +named_conf_options: /etc/named.conf +named_conf_local: /etc/named.conf +named_checkconf: /usr/bin/named-checkconf \ No newline at end of file diff --git a/roles/nameserver/vars/Debian.yml b/roles/nameserver/vars/Debian.yml index d6b249e..39af645 100644 --- a/roles/nameserver/vars/Debian.yml +++ b/roles/nameserver/vars/Debian.yml @@ -1,2 +1,9 @@ bind_package: bind9 -perl_readbackwards: libfile-readbackwards-perl \ No newline at end of file +unbound_package: unbound +perl_readbackwards: libfile-readbackwards-perl + +# named / bind specific +named_conf_zones: /etc/bind/named.conf.default-zones +named_conf_options: /etc/bind/named.conf.options +named_conf_local: /etc/bind/named.conf.local +named_checkconf: /usr/sbin/named-checkconf \ No newline at end of file diff --git a/roles/nameserver/vars/Ubuntu.yml b/roles/nameserver/vars/Ubuntu.yml index d6b249e..39af645 100644 --- a/roles/nameserver/vars/Ubuntu.yml +++ b/roles/nameserver/vars/Ubuntu.yml @@ -1,2 +1,9 @@ bind_package: bind9 -perl_readbackwards: libfile-readbackwards-perl \ No newline at end of file +unbound_package: unbound +perl_readbackwards: libfile-readbackwards-perl + +# named / bind specific +named_conf_zones: /etc/bind/named.conf.default-zones +named_conf_options: /etc/bind/named.conf.options +named_conf_local: /etc/bind/named.conf.local +named_checkconf: /usr/sbin/named-checkconf \ No newline at end of file diff --git a/roles/server/files/sudoers b/roles/server/files/sudoers index 0cee923..c666608 100644 --- a/roles/server/files/sudoers +++ b/roles/server/files/sudoers @@ -1 +1,2 @@ Debian-snmp ALL = NOPASSWD: /etc/snmp/bind, /etc/snmp/fail2ban, /etc/snmp/docker-stats.sh, /etc/snmp/mailcow-dockerized-postfix +Debian-snmp ALL = (postgres) NOPASSWD: /etc/snmp/postgres diff --git a/roles/server/tasks/utilities/snmpd.yml b/roles/server/tasks/utilities/snmpd.yml index 503bc32..4bab22d 100644 --- a/roles/server/tasks/utilities/snmpd.yml +++ b/roles/server/tasks/utilities/snmpd.yml @@ -17,7 +17,7 @@ - name: server | snmpd | insert anchors to snmpd.conf blockinfile: - path: "/etc/snmp/snmpd.conf" + path: "{{ snmpd_conf }}" marker: "# {mark} ANSIBLE MANAGED BLOCK" # not required. The marker line template. C({mark}) will be replaced with the values C(in marker_begin) (default="BEGIN") and C(marker_end) (default="END"). Using a custom marker without the C({mark}) variable may result in the block being repeatedly inserted on subsequent playbook runs. block: | ################################################################################ @@ -35,13 +35,13 @@ - name: server | snmpd | setup ACLs lineinfile: - path: "/etc/snmp/snmpd.conf" # required. The file to modify. Before Ansible 2.3 this option was only usable as I(dest), I(destfile) and I(name). + path: "{{ snmpd_conf }}" # required. The file to modify. Before Ansible 2.3 this option was only usable as I(dest), I(destfile) and I(name). line: "rouser {{snmp_user }} authpriv" insertafter: "# SECTION: custom settings" - name: server | snmpd | enable service on wireguard interface lineinfile: - path: "/etc/snmp/snmpd.conf" + path: "{{ snmpd_conf }}" regexp: "^agentaddress.*$" state: present line: "agentaddress 127.0.0.1,{{ wg_local_ip | ipaddr('address') }},[::1]" @@ -49,7 +49,7 @@ - name: server | snmpd | enable service on all interfaces lineinfile: - path: "/etc/snmp/snmpd.conf" + path: "{{ snmpd_conf }}" regexp: "^agentaddress.*$" state: present line: "agentaddress udp:161,udp6:[::1]:161" @@ -71,7 +71,7 @@ - name: server | snmpd | configure extends lineinfile: - path: "/etc/snmp/snmpd.conf" + path: "{{ snmpd_conf }}" state: present line: "extend {{ item.service }} '{{ item.script }}'" insertafter: "# SECTION: custom settings" diff --git a/roles/webserver/tasks/configure_nginx_snmpd.yml b/roles/webserver/tasks/configure_nginx_snmpd.yml index 139c6a3..7a15834 100644 --- a/roles/webserver/tasks/configure_nginx_snmpd.yml +++ b/roles/webserver/tasks/configure_nginx_snmpd.yml @@ -8,7 +8,7 @@ - name: webserver | snmpd | configure extend lineinfile: - path: "/etc/snmp/snmpd.conf" + path: "{{ snmpd_conf }}" state: present line: "extend nginx /etc/snmp/nginx" insertafter: "# SECTION: custom settings"