From 865e2f05621fc10f3d332d3840707997c0b94abf Mon Sep 17 00:00:00 2001 From: Stonewall Jackson Date: Mon, 12 Jun 2023 21:02:22 -0400 Subject: add mastodon role --- inventory-example/10-hosts | 1 + inventory-example/20-by-hostname.yml | 1 + inventory-example/group_vars/all/firefox.yml | 2 + inventory-example/group_vars/all/freeipa.yml | 3 + inventory-example/group_vars/all/mastodon.yml | 13 +++ inventory-example/group_vars/all/nsd.yml | 1 + inventory-example/group_vars/all/postgres.yml | 1 + inventory-example/group_vars/all/vault.yml | 7 ++ playbooks/mastodon.yml | 17 +++ playbooks/populate_domain.yml | 2 + playbooks/site.yml | 1 + playbooks/webserver_public_example.yml | 1 + .../usr/local/share/dirsrv/schema/mastodon.ldif | 3 + roles/freeipa_server/tasks/custom_schema.yml | 51 +++++++++ roles/mastodon/defaults/main.yml | 23 ++++ roles/mastodon/handlers/main.yml | 8 ++ roles/mastodon/meta/main.yml | 14 +++ roles/mastodon/tasks/database.yml | 23 ++++ roles/mastodon/tasks/freeipa.yml | 8 ++ roles/mastodon/tasks/main.yml | 121 +++++++++++++++++++++ .../etc/systemd/system/mastodon-cleanup.service.j2 | 49 +++++++++ .../etc/systemd/system/mastodon-cleanup.timer.j2 | 10 ++ .../etc/systemd/system/mastodon-sidekiq.service.j2 | 52 +++++++++ .../systemd/system/mastodon-streaming.service.j2 | 51 +++++++++ .../etc/systemd/system/mastodon-web.service.j2 | 52 +++++++++ .../opt/mastodon/mastodon/.env.production.j2 | 59 ++++++++++ roles/mastodon/vars/main.yml | 58 ++++++++++ 27 files changed, 632 insertions(+) create mode 100644 inventory-example/group_vars/all/mastodon.yml create mode 100644 playbooks/mastodon.yml create mode 100644 roles/freeipa_server/files/usr/local/share/dirsrv/schema/mastodon.ldif create mode 100644 roles/mastodon/defaults/main.yml create mode 100644 roles/mastodon/handlers/main.yml create mode 100644 roles/mastodon/meta/main.yml create mode 100644 roles/mastodon/tasks/database.yml create mode 100644 roles/mastodon/tasks/freeipa.yml create mode 100644 roles/mastodon/tasks/main.yml create mode 100644 roles/mastodon/templates/etc/systemd/system/mastodon-cleanup.service.j2 create mode 100644 roles/mastodon/templates/etc/systemd/system/mastodon-cleanup.timer.j2 create mode 100644 roles/mastodon/templates/etc/systemd/system/mastodon-sidekiq.service.j2 create mode 100644 roles/mastodon/templates/etc/systemd/system/mastodon-streaming.service.j2 create mode 100644 roles/mastodon/templates/etc/systemd/system/mastodon-web.service.j2 create mode 100644 roles/mastodon/templates/opt/mastodon/mastodon/.env.production.j2 create mode 100644 roles/mastodon/vars/main.yml diff --git a/inventory-example/10-hosts b/inventory-example/10-hosts index 90e1acf..43306d6 100644 --- a/inventory-example/10-hosts +++ b/inventory-example/10-hosts @@ -36,6 +36,7 @@ dmz-xmpp1 ip=10.10.19.5 cname=xmpp dmz-turn1 ip=10.10.19.6 cname=turn dmz-git1 ip=10.10.19.13 dmz-matrix1 ip=10.10.19.14 cores=4 ram=8g disk=256g +dmz-mastodon1 ip=10.10.19.15 cores=4 ram=4g disk=256g dmz-asterisk1 ip=10.10.14.10 cname=asterisk cores=4 [unmanaged] diff --git a/inventory-example/20-by-hostname.yml b/inventory-example/20-by-hostname.yml index db1ba15..de5f253 100644 --- a/inventory-example/20-by-hostname.yml +++ b/inventory-example/20-by-hostname.yml @@ -42,3 +42,4 @@ groups: turn_servers: inventory_hostname is match('(dmz-)?turn[0-9]') asterisk_servers: inventory_hostname is match('(dmz-)?asterisk[0-9]') matrix_servers: inventory_hostname is match('(dmz-)?matrix[0-9]') + mastodon_servers: inventory_hostname is match('(dmz-)?mastodon[0-9]') diff --git a/inventory-example/group_vars/all/firefox.yml b/inventory-example/group_vars/all/firefox.yml index 07d227b..36d7b1f 100644 --- a/inventory-example/group_vars/all/firefox.yml +++ b/inventory-example/group_vars/all/firefox.yml @@ -49,6 +49,8 @@ firefox_managed_bookmarks: url: 'https://invidious.{{ domain }}' - name: Jellyfin url: 'https://jellyfin.{{ domain }}' + - name: Mastodon + url: 'https://mastodon.{{ domain }}' - name: Matrix url: 'https://matrix.{{ domain }}' - name: Nagios diff --git a/inventory-example/group_vars/all/freeipa.yml b/inventory-example/group_vars/all/freeipa.yml index 15b7259..5026212 100644 --- a/inventory-example/group_vars/all/freeipa.yml +++ b/inventory-example/group_vars/all/freeipa.yml @@ -131,6 +131,9 @@ freeipa_groups: - name: role-matrix-access group: doefamily + - name: role-mastodon-access + group: doefamily + freeipa_hbac_rules: - name: sysadmins_ssh_and_console_to_all description: allow sysadmins to ssh to all hosts diff --git a/inventory-example/group_vars/all/mastodon.yml b/inventory-example/group_vars/all/mastodon.yml new file mode 100644 index 0000000..932d51d --- /dev/null +++ b/inventory-example/group_vars/all/mastodon.yml @@ -0,0 +1,13 @@ +mastodon_domain: example.com +mastodon_web_domain: mastodon.example.com +mastodon_db_name: mastodon +mastodon_db_user: s-mastodon +mastodon_db_password: '{{ vault_mastodon_db_password }}' +mastodon_sysaccount_password: '{{ vault_mastodon_sysaccount_password }}' +mastodon_login_cidrs: + - '{{ vlans.trusted.cidr }}' + +mastodon_secret_key_base: '{{ vault_mastodon_secret_key_base }}' +mastodon_otp_secret: '{{ vault_mastodon_otp_secret }}' +mastodon_vapid_private_key: '{{ vault_mastodon_vapid_private_key }}' +mastodon_vapid_public_key: changeme diff --git a/inventory-example/group_vars/all/nsd.yml b/inventory-example/group_vars/all/nsd.yml index d40351b..2c21a70 100644 --- a/inventory-example/group_vars/all/nsd.yml +++ b/inventory-example/group_vars/all/nsd.yml @@ -35,6 +35,7 @@ nsd_zones: turn1 IN A 203.0.113.58 pbx1 IN A 203.0.113.59 matrix IN A 203.0.113.60 + mastodon IN A 203.0.113.61 www IN CNAME www1 xmpp IN CNAME xmpp1 conference IN CNAME xmpp1 diff --git a/inventory-example/group_vars/all/postgres.yml b/inventory-example/group_vars/all/postgres.yml index be90568..b38f4c0 100644 --- a/inventory-example/group_vars/all/postgres.yml +++ b/inventory-example/group_vars/all/postgres.yml @@ -2,3 +2,4 @@ postgresql_host: postgres.{{ domain }} postgresql_inventory_host: "{{ postgresql_host.split('.')[0] }}" postgresql_password_users: - '{{ invidious_db_user }}' + - '{{ mastodon_db_user }}' diff --git a/inventory-example/group_vars/all/vault.yml b/inventory-example/group_vars/all/vault.yml index 58b597a..18b57bb 100644 --- a/inventory-example/group_vars/all/vault.yml +++ b/inventory-example/group_vars/all/vault.yml @@ -65,6 +65,13 @@ vault_invidious_hmac_key: changeme vault_jellyfin_sysaccount_password: changeme +# mastodon +vault_mastodon_sysaccount_password: changeme +vault_mastodon_secret_key_base: changeme +vault_mastodon_otp_secret: changeme +vault_mastodon_vapid_private_key: changeme + + # mediawiki vault_mediawiki_admin_password: changeme vault_mediawiki_upgrade_key: changeme diff --git a/playbooks/mastodon.yml b/playbooks/mastodon.yml new file mode 100644 index 0000000..8c7b381 --- /dev/null +++ b/playbooks/mastodon.yml @@ -0,0 +1,17 @@ +- name: configure mastodon servers + hosts: mastodon_servers + roles: + - role: common + tags: common + + - role: mastodon + tags: mastodon + + - role: apache_vhost + apache_server_name: '{{ mastodon_web_domain }}' + apache_server_aliases: [] + apache_letsencrypt: yes + apache_redirect_to_https: yes + apache_document_root: '{{ mastodon_webroot }}' + apache_config: '{{ mastodon_apache_config }}' + tags: apache diff --git a/playbooks/populate_domain.yml b/playbooks/populate_domain.yml index acb1ec7..c118af9 100644 --- a/playbooks/populate_domain.yml +++ b/playbooks/populate_domain.yml @@ -24,6 +24,8 @@ attributes: mailAlternateAddress: '{{ item.mail_aliases | default([]) }}' jid: '{{ item.jid | default([]) }}' + mastodonUsername: '{{ item.mastodon_id | default([]) }}' + matrixUsername: '{{ item.mxid | default([]) }}' bind_dn: uid={{ ipa_user }},{{ freeipa_user_basedn }} bind_pw: '{{ ipa_pass }}' server_uri: ldaps://{{ ipa_host }} diff --git a/playbooks/site.yml b/playbooks/site.yml index fa79f8d..48b6144 100644 --- a/playbooks/site.yml +++ b/playbooks/site.yml @@ -36,3 +36,4 @@ - import_playbook: xmpp.yml - import_playbook: asterisk.yml - import_playbook: matrix.yml +- import_playbook: mastodon.yml diff --git a/playbooks/webserver_public_example.yml b/playbooks/webserver_public_example.yml index d9cb468..69a3254 100644 --- a/playbooks/webserver_public_example.yml +++ b/playbooks/webserver_public_example.yml @@ -11,6 +11,7 @@ apache_letsencrypt: yes apache_document_root: /var/www/www.example.com apache_config: | + Redirect permanent /.well-known/webfinger https://mastodon.example.com/.well-known/webfinger Alias /.well-known/matrix /var/www/well-known/example.com/matrix tags: apache diff --git a/roles/freeipa_server/files/usr/local/share/dirsrv/schema/mastodon.ldif b/roles/freeipa_server/files/usr/local/share/dirsrv/schema/mastodon.ldif new file mode 100644 index 0000000..f90bc66 --- /dev/null +++ b/roles/freeipa_server/files/usr/local/share/dirsrv/schema/mastodon.ldif @@ -0,0 +1,3 @@ +dn: cn=config +attributetypes: ( 2.25.10508909625911985622145696820691585120.4 NAME 'mastodonUsername' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Extending FreeIPA' ) +objectclasses: ( 2.25.10508909625911985622145696820691585120.3 NAME 'mastodonUser' AUXILIARY MAY mastodonUsername X-ORIGIN 'Extending FreeIPA' ) diff --git a/roles/freeipa_server/tasks/custom_schema.yml b/roles/freeipa_server/tasks/custom_schema.yml index 73456e3..849b524 100644 --- a/roles/freeipa_server/tasks/custom_schema.yml +++ b/roles/freeipa_server/tasks/custom_schema.yml @@ -11,6 +11,7 @@ loop: - jid - matrix + - mastodon # begin JIDObject schema @@ -109,6 +110,54 @@ when: matrixusername_index.changed # end matrixUser schema +# begin mastodonUser schema +- name: check if mastodonUser exists in schema + shell: ldapsearch -QLLL -s base -b cn=schema objectclasses | grep -q mastodonUser + changed_when: no + failed_when: no + register: ldapsearch_mastodonuser + +- block: + - name: extend freeipa schema for mastodon usernames + command: ipa-ldap-updater --schema-file '{{ freeipa_custom_schema_dir }}/mastodon.ldif' + + - name: restart httpd + systemd: + name: httpd + state: restarted + when: ldapsearch_mastodonuser.rc != 0 + +- name: add index to mastodonUsername attribute + ldap_entry: + dn: 'cn=mastodonUsername,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config' + objectClass: + - top + - nsIndex + attributes: + cn: mastodonUsername + nsSystemIndex: false + nsIndexType: eq + bind_dn: cn=Directory Manager + bind_pw: '{{ freeipa_ds_password }}' + server_uri: ldaps://{{ ipa_host }} + register: mastodonusername_index + +- name: regenerate indexes for mastodonUsername attribute + ldap_entry: + dn: cn=mastodonusernameindex,cn=index,cn=tasks,cn=config + objectClass: + - top + - extensibleObject + attributes: + cn: mastodonusernameindex + nsInstance: userRoot + nsIndexAttribute: 'mastodonUsername:eq' + bind_dn: cn=Directory Manager + bind_pw: '{{ freeipa_ds_password }}' + server_uri: ldaps://{{ ipa_host }} + when: mastodonusername_index.changed +# end mastodonUser schema + - name: add default user object classes ldap_attrs: dn: cn=ipaConfig,cn=etc,{{ freeipa_basedn }} @@ -117,6 +166,7 @@ - mailRecipient - JIDObject - matrixUser + - mastodonUser state: present bind_dn: cn=Directory Manager bind_pw: '{{ freeipa_ds_password }}' @@ -142,6 +192,7 @@ - mailAlternateAddress - jid - matrixUsername + - mastodonUsername action: member state: present diff --git a/roles/mastodon/defaults/main.yml b/roles/mastodon/defaults/main.yml new file mode 100644 index 0000000..d9bab79 --- /dev/null +++ b/roles/mastodon/defaults/main.yml @@ -0,0 +1,23 @@ +mastodon_version: 4.1.2 + +mastodon_access_group: role-mastodon-access +mastodon_db_user: s-mastodon +# mastodon_db_password +mastodon_db_host: '{{ postgresql_host }}' +mastodon_db_name: mastodon +mastodon_ldap_host: '{{ freeipa_hosts | first }}' + +mastodon_domain: '{{ email_domain }}' +mastodon_web_domain: '{{ ansible_fqdn }}' +mastodon_email_from: 'mastodon-noreply@{{ email_domain }}' + +mastodon_default_locale: en + +mastodon_registrations: close + +mastodon_redis_port: 6379 +mastodon_web_port: 8008 +mastodon_streaming_port: 8009 + +mastodon_sysaccount_username: mastodon +#mastodon_sysaccount_password diff --git a/roles/mastodon/handlers/main.yml b/roles/mastodon/handlers/main.yml new file mode 100644 index 0000000..20fe804 --- /dev/null +++ b/roles/mastodon/handlers/main.yml @@ -0,0 +1,8 @@ +- name: restart mastodon + systemd: + name: '{{ item }}' + state: restarted + loop: + - mastodon-web + - mastodon-streaming + - mastodon-sidekiq diff --git a/roles/mastodon/meta/main.yml b/roles/mastodon/meta/main.yml new file mode 100644 index 0000000..8c0b12b --- /dev/null +++ b/roles/mastodon/meta/main.yml @@ -0,0 +1,14 @@ +dependencies: + - role: yum + yum_repositories: + - epel + - rpmfusion-free + tags: yum + + - role: freeipa_system_account + system_account_username: '{{ mastodon_sysaccount_username }}' + system_account_password: '{{ mastodon_sysaccount_password }}' + + - role: redis + redis_port: '{{ mastodon_redis_port }}' + tags: redis diff --git a/roles/mastodon/tasks/database.yml b/roles/mastodon/tasks/database.yml new file mode 100644 index 0000000..37f6dcd --- /dev/null +++ b/roles/mastodon/tasks/database.yml @@ -0,0 +1,23 @@ +- name: create database user + postgresql_user: + name: '{{ mastodon_db_user }}' + password: '{{ mastodon_db_password }}' + role_attr_flags: CREATEDB + state: present + environment: + PGOPTIONS: "-c password_encryption=scram-sha-256" + delegate_to: "{{ postgresql_inventory_host }}" + become: yes + become_user: postgres + register: mastodon_db_user + +- name: create database schema + command: + chdir: '{{ mastodon_install_dir }}' + cmd: 'bundle exec rake db:setup' + environment: + RAILS_ENV: production + SAFETY_ASSURED: 1 + become: yes + become_user: '{{ mastodon_user }}' + when: mastodon_db_user.changed diff --git a/roles/mastodon/tasks/freeipa.yml b/roles/mastodon/tasks/freeipa.yml new file mode 100644 index 0000000..ee68b13 --- /dev/null +++ b/roles/mastodon/tasks/freeipa.yml @@ -0,0 +1,8 @@ +- name: create access group + ipagroup: + ipaadmin_principal: '{{ ipa_user }}' + ipaadmin_password: '{{ ipa_pass }}' + name: '{{ mastodon_access_group }}' + nonposix: yes + state: present + run_once: yes diff --git a/roles/mastodon/tasks/main.yml b/roles/mastodon/tasks/main.yml new file mode 100644 index 0000000..7ff23dd --- /dev/null +++ b/roles/mastodon/tasks/main.yml @@ -0,0 +1,121 @@ +- name: install packages + dnf: + name: '{{ mastodon_packages }}' + state: present + +- name: add local user + user: + name: '{{ mastodon_user }}' + system: yes + home: '{{ mastodon_home }}' + shell: /sbin/nologin + create_home: no + +- import_tasks: freeipa.yml + +- name: create home directory + file: + path: '{{ mastodon_home }}' + owner: '{{ mastodon_user }}' + group: '{{ mastodon_user }}' + mode: 0755 + state: directory + +- name: clone repo + git: + repo: '{{ mastodon_git_repo }}' + dest: '{{ mastodon_install_dir }}' + version: 'v{{ mastodon_version }}' + update: yes + force: yes + become: yes + become_user: '{{ mastodon_user }}' + register: mastodon_git + +- name: set selinux context on writeable directories + sefcontext: + target: '{{ mastodon_webroot }}(/.*)?' + setype: httpd_sys_content_t + state: present + register: mastodon_webroot_sefcontext + tags: selinux + +- name: apply selinux context to writeable directories + command: 'restorecon -R {{ mastodon_webroot }}' + when: mastodon_webroot_sefcontext.changed + tags: selinux + +- name: build mastodon + command: + chdir: '{{ mastodon_install_dir }}' + cmd: '{{ item }}' + loop: + - "bundle config deployment 'true'" + - "bundle config without 'development test'" + - 'bundle install -j{{ ansible_processor_vcpus }}' + - yarn install --pure-lockfile + become: yes + become_user: '{{ mastodon_user }}' + notify: restart mastodon + when: mastodon_git.changed + +- name: generate .env.production + template: + src: '{{ mastodon_install_dir[1:] }}/.env.production.j2' + dest: '{{ mastodon_install_dir }}/.env.production' + owner: '{{ mastodon_user }}' + group: '{{ mastodon_user }}' + mode: 0600 + notify: restart mastodon + +- import_tasks: database.yml + +- name: precompile assets + command: + chdir: '{{ mastodon_install_dir }}' + cmd: 'bundle exec rake assets:precompile' + environment: + NODE_OPTIONS: --openssl-legacy-provider + RAILS_ENV: production + become: yes + become_user: '{{ mastodon_user }}' + when: mastodon_git.changed + +- name: create systemd units + template: + src: etc/systemd/system/{{ item }}.j2 + dest: /etc/systemd/system/{{ item }} + loop: + - mastodon-sidekiq.service + - mastodon-streaming.service + - mastodon-web.service + - mastodon-cleanup.service + - mastodon-cleanup.timer + register: mastodon_systemd_units + notify: restart mastodon + +- name: reload systemd daemons + systemd: + daemon_reload: yes + when: mastodon_systemd_units.changed + +- name: start mastodon + systemd: + name: '{{ item }}' + enabled: yes + state: started + loop: + - mastodon-sidekiq.service + - mastodon-streaming.service + - mastodon-web.service + - mastodon-cleanup.timer + +- name: configure registrations + command: + chdir: '{{ mastodon_install_dir }}' + cmd: './bin/tootctl settings registrations {{ mastodon_registrations }}' + environment: + RAILS_ENV: production + become: yes + become_user: '{{ mastodon_user }}' + changed_when: no diff --git a/roles/mastodon/templates/etc/systemd/system/mastodon-cleanup.service.j2 b/roles/mastodon/templates/etc/systemd/system/mastodon-cleanup.service.j2 new file mode 100644 index 0000000..3db1ea3 --- /dev/null +++ b/roles/mastodon/templates/etc/systemd/system/mastodon-cleanup.service.j2 @@ -0,0 +1,49 @@ +[Unit] +Description=mastodon-cleanup +After=network.target + +[Service] +Type=oneshot +User={{ mastodon_user }} +WorkingDirectory={{ mastodon_install_dir }} +Environment="RAILS_ENV=production" +ExecStart={{ mastodon_install_dir }}/bin/tootctl media remove +ExecStart={{ mastodon_install_dir }}/bin/tootctl preview_cards remove +# Proc filesystem +ProcSubset=pid +ProtectProc=invisible +# Capabilities +CapabilityBoundingSet= +# Security +NoNewPrivileges=true +# Sandboxing +ProtectSystem=strict +PrivateTmp=true +PrivateDevices=true +PrivateUsers=true +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_INET +RestrictAddressFamilies=AF_INET6 +RestrictAddressFamilies=AF_NETLINK +RestrictAddressFamilies=AF_UNIX +RestrictNamespaces=true +LockPersonality=true +RestrictRealtime=true +RestrictSUIDSGID=true +RemoveIPC=true +PrivateMounts=true +ProtectClock=true +# System Call Filtering +SystemCallArchitectures=native +SystemCallFilter=~@cpu-emulation @debug @ipc @mount @obsolete @privileged @setuid +SystemCallFilter=@chown +SystemCallFilter=pipe +SystemCallFilter=pipe2 +ReadWritePaths={{ mastodon_install_dir }} + +[Install] +WantedBy=multi-user.target diff --git a/roles/mastodon/templates/etc/systemd/system/mastodon-cleanup.timer.j2 b/roles/mastodon/templates/etc/systemd/system/mastodon-cleanup.timer.j2 new file mode 100644 index 0000000..a767551 --- /dev/null +++ b/roles/mastodon/templates/etc/systemd/system/mastodon-cleanup.timer.j2 @@ -0,0 +1,10 @@ +[Unit] +Description=Mastodon cleanup on calendar interval + +[Timer] +OnCalendar=weekly +AccuracySec=1h +Persistent=true + +[Install] +WantedBy=multi-user.target diff --git a/roles/mastodon/templates/etc/systemd/system/mastodon-sidekiq.service.j2 b/roles/mastodon/templates/etc/systemd/system/mastodon-sidekiq.service.j2 new file mode 100644 index 0000000..9b9abfd --- /dev/null +++ b/roles/mastodon/templates/etc/systemd/system/mastodon-sidekiq.service.j2 @@ -0,0 +1,52 @@ +[Unit] +Description=mastodon-sidekiq +After=network.target + +[Service] +Type=simple +User={{ mastodon_user }} +WorkingDirectory={{ mastodon_install_dir }} +Environment="RAILS_ENV=production" +Environment="DB_POOL=25" +Environment="MALLOC_ARENA_MAX=2" +ExecStart=/usr/bin/bundle exec sidekiq -c 25 +TimeoutSec=15 +Restart=always +# Proc filesystem +ProcSubset=pid +ProtectProc=invisible +# Capabilities +CapabilityBoundingSet= +# Security +NoNewPrivileges=true +# Sandboxing +ProtectSystem=strict +PrivateTmp=true +PrivateDevices=true +PrivateUsers=true +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_INET +RestrictAddressFamilies=AF_INET6 +RestrictAddressFamilies=AF_NETLINK +RestrictAddressFamilies=AF_UNIX +RestrictNamespaces=true +LockPersonality=true +RestrictRealtime=true +RestrictSUIDSGID=true +RemoveIPC=true +PrivateMounts=true +ProtectClock=true +# System Call Filtering +SystemCallArchitectures=native +SystemCallFilter=~@cpu-emulation @debug @ipc @mount @obsolete @privileged @setuid +SystemCallFilter=@chown +SystemCallFilter=pipe +SystemCallFilter=pipe2 +ReadWritePaths={{ mastodon_install_dir }} + +[Install] +WantedBy=multi-user.target diff --git a/roles/mastodon/templates/etc/systemd/system/mastodon-streaming.service.j2 b/roles/mastodon/templates/etc/systemd/system/mastodon-streaming.service.j2 new file mode 100644 index 0000000..48f58ab --- /dev/null +++ b/roles/mastodon/templates/etc/systemd/system/mastodon-streaming.service.j2 @@ -0,0 +1,51 @@ +[Unit] +Description=mastodon-streaming +After=network.target + +[Service] +Type=simple +User={{ mastodon_user }} +WorkingDirectory={{ mastodon_install_dir }} +Environment="NODE_ENV=production" +Environment="PORT={{ mastodon_streaming_port }}" +Environment="STREAMING_CLUSTER_NUM=1" +ExecStart=/usr/bin/node ./streaming +TimeoutSec=15 +Restart=always +# Proc filesystem +ProcSubset=pid +ProtectProc=invisible +# Capabilities +CapabilityBoundingSet= +# Security +NoNewPrivileges=true +# Sandboxing +ProtectSystem=strict +PrivateTmp=true +PrivateDevices=true +PrivateUsers=true +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_INET +RestrictAddressFamilies=AF_INET6 +RestrictAddressFamilies=AF_NETLINK +RestrictAddressFamilies=AF_UNIX +RestrictNamespaces=true +LockPersonality=true +RestrictRealtime=true +RestrictSUIDSGID=true +RemoveIPC=true +PrivateMounts=true +ProtectClock=true +# System Call Filtering +SystemCallArchitectures=native +SystemCallFilter=~@cpu-emulation @debug @ipc @memlock @mount @obsolete @privileged @resources @setuid +SystemCallFilter=pipe +SystemCallFilter=pipe2 +ReadWritePaths={{ mastodon_install_dir }} + +[Install] +WantedBy=multi-user.target diff --git a/roles/mastodon/templates/etc/systemd/system/mastodon-web.service.j2 b/roles/mastodon/templates/etc/systemd/system/mastodon-web.service.j2 new file mode 100644 index 0000000..6a3fd03 --- /dev/null +++ b/roles/mastodon/templates/etc/systemd/system/mastodon-web.service.j2 @@ -0,0 +1,52 @@ +[Unit] +Description=mastodon-web +After=network.target + +[Service] +Type=simple +User={{ mastodon_user }} +WorkingDirectory={{ mastodon_install_dir }} +Environment="RAILS_ENV=production" +Environment="PORT={{ mastodon_web_port }}" +ExecStart=/usr/bin/bundle exec puma -C config/puma.rb +ExecReload=/bin/kill -SIGUSR1 $MAINPID +TimeoutSec=15 +Restart=always +# Proc filesystem +ProcSubset=pid +ProtectProc=invisible +# Capabilities +CapabilityBoundingSet= +# Security +NoNewPrivileges=true +# Sandboxing +ProtectSystem=strict +PrivateTmp=true +PrivateDevices=true +PrivateUsers=true +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_INET +RestrictAddressFamilies=AF_INET6 +RestrictAddressFamilies=AF_NETLINK +RestrictAddressFamilies=AF_UNIX +RestrictNamespaces=true +LockPersonality=true +RestrictRealtime=true +RestrictSUIDSGID=true +RemoveIPC=true +PrivateMounts=true +ProtectClock=true +# System Call Filtering +SystemCallArchitectures=native +SystemCallFilter=~@cpu-emulation @debug @ipc @mount @obsolete @privileged @setuid +SystemCallFilter=@chown +SystemCallFilter=pipe +SystemCallFilter=pipe2 +ReadWritePaths={{ mastodon_install_dir }} + +[Install] +WantedBy=multi-user.target diff --git a/roles/mastodon/templates/opt/mastodon/mastodon/.env.production.j2 b/roles/mastodon/templates/opt/mastodon/mastodon/.env.production.j2 new file mode 100644 index 0000000..03af34a --- /dev/null +++ b/roles/mastodon/templates/opt/mastodon/mastodon/.env.production.j2 @@ -0,0 +1,59 @@ +# Federation +# ---------- +# This identifies your server and cannot be changed safely later +# ---------- +LOCAL_DOMAIN={{ mastodon_domain }} +WEB_DOMAIN={{ mastodon_web_domain }} + +DEFAULT_LOCALE={{ mastodon_default_locale }} + +# Redis +# ----- +REDIS_HOST=localhost +REDIS_PORT={{ mastodon_redis_port }} + +# PostgreSQL +# ---------- +DB_SSLMODE=verify-full +DATABASE_URL=postgresql://{{ mastodon_db_user }}:{{ mastodon_db_password}}@{{ mastodon_db_host }}/{{ mastodon_db_name }}?sslmode=verify-full&sslrootcert=/etc/pki/tls/certs/ca-bundle.crt + +# Secrets +# ------- +# Make sure to use `rake secret` to generate secrets +# ------- +SECRET_KEY_BASE={{ mastodon_secret_key_base }} +OTP_SECRET={{ mastodon_otp_secret }} + +# Web Push +# -------- +# Generate with `rake mastodon:webpush:generate_vapid_key` +# -------- +VAPID_PRIVATE_KEY={{ mastodon_vapid_public_key }} +VAPID_PUBLIC_KEY={{ mastodon_vapid_private_key }} + +# Sending mail +# ------------ +SMTP_SERVER=localhost +SMTP_PORT=25 +SMTP_FROM_ADDRESS={{ mastodon_email_from }} + +# IP and session retention +# ----------------------- +# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml +# to be less than daily if you lower IP_RETENTION_PERIOD below two days (172800). +# ----------------------- +IP_RETENTION_PERIOD=31556952 +SESSION_RETENTION_PERIOD=31556952 + +# LDAP +# ---- +LDAP_ENABLED=true +LDAP_HOST={{ mastodon_ldap_host }} +LDAP_PORT=636 +LDAP_METHOD=simple_tls +LDAP_BASE={{ freeipa_user_basedn }} +LDAP_BIND_DN=uid={{ mastodon_sysaccount_username }},{{ freeipa_sysaccount_basedn }} +LDAP_PASSWORD={{ mastodon_sysaccount_password }} +LDAP_SEARCH_FILTER=(&(%{uid}=%{email})(memberOf=cn={{ mastodon_access_group }},{{ freeipa_group_basedn }})) +LDAP_MAIL=mail +LDAP_UID=mastodonUsername diff --git a/roles/mastodon/vars/main.yml b/roles/mastodon/vars/main.yml new file mode 100644 index 0000000..cede4a0 --- /dev/null +++ b/roles/mastodon/vars/main.yml @@ -0,0 +1,58 @@ +mastodon_packages: + - nodejs + - yarnpkg + - gcc + - g++ + - libicu-devel + - zlib-devel + - openssl-devel + - libidn-devel + - ruby-devel + - libpq-devel + - git + - ruby + - ImageMagick + - ffmpeg + +mastodon_keytab: /var/lib/gssproxy/clients/{{ mastodon_user }}.keytab +mastodon_home: /opt/mastodon +mastodon_user: mastodon +mastodon_install_dir: '{{ mastodon_home }}/mastodon' +mastodon_webroot: '{{ mastodon_install_dir }}/public' +mastodon_git_repo: https://github.com/mastodon/mastodon + +mastodon_apache_config: | + {% if mastodon_login_cidrs %} + + {% for cidr in mastodon_login_cidrs %} + Require ip {{ cidr }} + {% endfor %} + + {% endif %} + + + Header always set Cache-Control "public, max-age=31536000, immutable" + Require all granted + + + ProxyPass /500.html ! + ProxyPass /sw.js ! + ProxyPass /robots.txt ! + ProxyPass /manifest.json ! + ProxyPass /browserconfig.xml ! + ProxyPass /mask-icon.svg ! + ProxyPass /inert.css ! + ProxyPassMatch ^(/.*\.(png|ico)$) ! + ProxyPassMatch ^/(assets|avatars|emoji|headers|packs|sounds|system) ! + + {{ apache_proxy_config }} + ProxyPass /api/v1/streaming ws://127.0.0.1:{{ mastodon_streaming_port }} + ProxyPassReverse /api/v1/streaming ws://127.0.0.1:{{ mastodon_streaming_port }} + ProxyPass / http://127.0.0.1:{{ mastodon_web_port }}/ + ProxyPassReverse / http://127.0.0.1:{{ mastodon_web_port }}/ + + ErrorDocument 500 /500.html + ErrorDocument 501 /500.html + ErrorDocument 502 /500.html + ErrorDocument 503 /500.html + ErrorDocument 504 /500.html -- cgit