From 0bac8bed8405772bd8b1096c15512b9f9b8ee0fd Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Fri, 23 Dec 2022 10:00:00 -0500 Subject: [PATCH 1/9] =?UTF-8?q?p10166=20R=C3=B4le=20pour=20mastodon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapps/mastodon/README.md | 71 ++++++ webapps/mastodon/defaults/main.yml | 24 ++ webapps/mastodon/handlers/main.yml | 2 + webapps/mastodon/meta/main.yml | 52 ++++ webapps/mastodon/tasks/main.yml | 210 ++++++++++++++++ webapps/mastodon/tasks/upgrade.yml | 80 ++++++ webapps/mastodon/templates/env.j2 | 235 ++++++++++++++++++ .../templates/mastodon-sidekiq.service.j2 | 23 ++ .../templates/mastodon-streaming.service.j2 | 21 ++ .../templates/mastodon-web.service.j2 | 23 ++ webapps/mastodon/templates/mastodon.target.j2 | 8 + webapps/mastodon/templates/vhost.j2 | 94 +++++++ webapps/mastodon/tests/inventory | 2 + webapps/mastodon/tests/test.yml | 5 + webapps/mastodon/vars/main.yml | 2 + 15 files changed, 852 insertions(+) create mode 100644 webapps/mastodon/README.md create mode 100644 webapps/mastodon/defaults/main.yml create mode 100644 webapps/mastodon/handlers/main.yml create mode 100644 webapps/mastodon/meta/main.yml create mode 100644 webapps/mastodon/tasks/main.yml create mode 100644 webapps/mastodon/tasks/upgrade.yml create mode 100644 webapps/mastodon/templates/env.j2 create mode 100644 webapps/mastodon/templates/mastodon-sidekiq.service.j2 create mode 100644 webapps/mastodon/templates/mastodon-streaming.service.j2 create mode 100644 webapps/mastodon/templates/mastodon-web.service.j2 create mode 100644 webapps/mastodon/templates/mastodon.target.j2 create mode 100644 webapps/mastodon/templates/vhost.j2 create mode 100644 webapps/mastodon/tests/inventory create mode 100644 webapps/mastodon/tests/test.yml create mode 100644 webapps/mastodon/vars/main.yml diff --git a/webapps/mastodon/README.md b/webapps/mastodon/README.md new file mode 100644 index 00000000..e12ef769 --- /dev/null +++ b/webapps/mastodon/README.md @@ -0,0 +1,71 @@ +Role Name +========= + +Ce rôle installe le serveur de Mastodon, une application libre de microblogage, libre et autohébergée. + +Requirements +------------ + +... + +Role Variables +-------------- + +Plusieurs des valeurs par défaut dans defaults/main.yml doivent être changées soit directement dans defaults/main.yml ou mieux encore en les supplantant ailleurs, par exemple dans votre playbook (voir l'exemple ci-bas). + +Dependencies +------------ + +Ce rôle Ansible dépend des rôles suivants : + +- nodejs +- postgresql +- redis +- elasticsearch +- rbenv +- nginx +- certbot + +Example Playbook +---------------- + +``` +- name: "Déployer un serveur Mastodon" + hosts: + - all + vars: + # Supplanter ici les variables du rôle + domains: ['votre-vrai-domaine.org'] + service: 'mon-mastodon' + db_host: 'localhost' + db_user: "{{ service }}" + db_name: "{{ service }}" + db_password: 'zKEh-CHANGEZ-MOI-qIKc' + app_secret_key_base: "" + app_otp_secret: "" + app_vapid_private_key: "" + app_vapid_public_key: "" + app_smtp_from_address: "mastodon@votre-vrai-domaine.org" + + pre_tasks: + - name: "Installer les rôles systèmes" + roles: + - { role: nodejs, nodejs_apt_version: 'node_16.x', nodejs_install_yarn: True } + - { role: postgresql } + - { role: redis } + - { role: elasticsearch } + - { role: nginx } + - { role: certbot } + roles: + - { role: webapps/mastodon , tags: "mastodon" } +``` + +License +------- + +BSD + +Author Information +------------------ + +Mathieu Gauthier-Pilote, administrateur de systèmes chez Evolix. diff --git a/webapps/mastodon/defaults/main.yml b/webapps/mastodon/defaults/main.yml new file mode 100644 index 00000000..d5b82550 --- /dev/null +++ b/webapps/mastodon/defaults/main.yml @@ -0,0 +1,24 @@ +--- +# defaults file for mastodon +system_dep: "['imagemagick', 'ffmpeg', 'libpq-dev', 'libxml2-dev', 'libxslt1-dev', 'file', 'git-core', 'g++', 'libprotobuf-dev', 'protobuf-compiler', 'pkg-config', 'nodejs', 'gcc', 'autoconf', 'bison', 'build-essential', 'libssl-dev', 'libyaml-dev', 'libreadline6-dev', 'zlib1g-dev', 'libncurses5-dev', 'libffi-dev', 'libgdbm-dev', 'nginx', 'redis-server', 'redis-tools', 'postgresql', 'postgresql-contrib', 'certbot', 'python3-certbot-nginx', 'libidn11-dev', 'libicu-dev', 'libjemalloc-dev', 'yarn']" +domains: ['exemple.evolix.org'] +git_url: 'https://github.com/mastodon/mastodon.git' +git_version: 'v4.0.2' +ruby_version: '3.0.4' +service: 'exemple' + +db_host: 'localhost' +db_user: "{{ service }}" +db_name: "{{ service }}_production" +db_password: 'CHANGE_ME' + +app_secret_key_base: "" +app_otp_secret: "" +app_vapid_private_key: "" +app_vapid_public_key: "" +app_smtp_server: "127.0.0.1" +app_smtp_port: "25" +app_smtp_from_address: "exemple@evolix.org" +app_smtp_auth_method: "none" +app_smtp_openssl_verify_mode: "none" +app_es_enabled: "false" diff --git a/webapps/mastodon/handlers/main.yml b/webapps/mastodon/handlers/main.yml new file mode 100644 index 00000000..ba8d85b1 --- /dev/null +++ b/webapps/mastodon/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for mastodon diff --git a/webapps/mastodon/meta/main.yml b/webapps/mastodon/meta/main.yml new file mode 100644 index 00000000..c572acc9 --- /dev/null +++ b/webapps/mastodon/meta/main.yml @@ -0,0 +1,52 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.1 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/webapps/mastodon/tasks/main.yml b/webapps/mastodon/tasks/main.yml new file mode 100644 index 00000000..fed52d83 --- /dev/null +++ b/webapps/mastodon/tasks/main.yml @@ -0,0 +1,210 @@ +--- +# tasks file for mastodon + +- name: Install main system dependencies + apt: + name: "{{ system_dep }}" + +- name: Add PostgreSQL user + postgresql_user: + name: "{{ db_user }}" + password: "{{ db_password }}" + role_attr_flags: CREATEDB + become_user: postgres + +- name: Add UNIX account + user: + name: "{{ service }}" + shell: /bin/bash +# umask: "0022" nécessite ansible-core 2.12 + +- name: Install Ruby for service user (rbenv) + include_role: + name: rbenv + vars: + - username: "{{ service }}" + - rbenv_ruby_version: "{{ ruby_version }}" + +- name: Clone Mastodon repo (git) + git: + repo: "{{ git_url }}" + dest: "~/mastodon/" + version: "{{ git_version | default(omit) }}" + #force: yes + update: yes + become_user: "{{ service }}" + +- block: + - name: Install bundler + shell: ". ~/.profile && gem install bundler --no-document" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Install gem dependencies + shell: ". ~/.profile && bundle install --deployment --without development test -j$(getconf _NPROCESSORS_ONLN)" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Install javascript dependencies + shell: ". ~/.profile && yarn install --pure-lockfile" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + become_user: "{{ service }}" + +- name: Template .env.production configuration file + template: + src: "env.j2" + dest: "~{{ service }}/mastodon/.env.production" + owner: "{{ service }}" + group: "{{ service }}" + mode: "0640" + +- name: Check if secrets need to be generated or not + shell: "grep -P SECRET_KEY_BASE=[[:alnum:]]{128} .env.production" + args: + chdir: "~/mastodon" + become_user: "{{ service }}" + register: secrets + failed_when: "secrets.rc == 2" + +- block: + - name: Generate secret for SECRET_KEY_BASE + shell: '. ~/.profile && sed -i -r "s/SECRET_KEY_BASE=/SECRET_KEY_BASE=$(RAILS_ENV=production bundle exec rake secret)/" .env.production' + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Generate secret for OTP_SECRET + shell: '. ~/.profile && sed -i -r "s/OTP_SECRET=/OTP_SECRET=$(RAILS_ENV=production bundle exec rake secret)/" .env.production' + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Generate secret for VAPID_PRIVATE_KEY and VAPID_PUBLIC_KEY + shell: . ~/.profile && RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key > vapid.tmp | head -1 | cut -c 19- + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Read VAPID_PRIVATE_KEY secret from temp file + shell: "cat vapid.tmp | head -1 | cut -c 19-" + args: + chdir: "~/mastodon" + register: app_vapid_private_key + - name: Read VAPID_PUBLIC_KEY secret from temp file + shell: "cat vapid.tmp | tail -1 | cut -c 18-" + args: + chdir: "~/mastodon" + register: app_vapid_public_key + - name: Delete secrets temp file + file: + path: "~/mastodon/vapid.tmp" + state: absent + - name: Write app_vapid_private_key to production .env file + lineinfile: + path: "~/mastodon/.env.production" + regexp: '^VAPID_PRIVATE_KEY=' + line: "VAPID_PRIVATE_KEY={{ app_vapid_private_key.stdout }}" + - name: Write app_vapid_public_key to production .env file + lineinfile: + path: "~/mastodon/.env.production" + regexp: '^VAPID_PUBLIC_KEY=' + line: "VAPID_PUBLIC_KEY={{ app_vapid_public_key.stdout }}" + become_user: "{{ service }}" + when: "secrets.rc == 1" + +- name: Check if mastodon database is already present or not + shell: | + psql -lqt | cut -d \| -f 1 | grep -qw {{ service }}_production + become_user: postgres + register: db_present + failed_when: "db_present.rc == 2" + +- name: Setup database schema if database not already present + shell: ". ~/.profile && RAILS_ENV=production SAFETY_ASSURED=1 bundle exec rails db:setup" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + become_user: "{{ service }}" + when: "db_present.rc == 1" + +- name: Precompile assets + shell: ". ~/.profile && RAILS_ENV=production bundle exec rails assets:precompile" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + become_user: "{{ service }}" + +- name: Add systemd target + template: + src: "mastodon.target.j2" + dest: "/etc/systemd/system/{{ service }}.target" + +- name: Add systemd web unit + template: + src: "mastodon-web.service.j2" + dest: "/etc/systemd/system/{{ service }}-web.service" + +- name: Add systemd sidekiq unit + template: + src: "mastodon-sidekiq.service.j2" + dest: "/etc/systemd/system/{{ service }}-sidekiq.service" + +- name: Add systemd streaming unit + template: + src: "mastodon-streaming.service.j2" + dest: "/etc/systemd/system/{{ service }}-streaming.service" + +- name: Enable systemd units + systemd: + name: "{{ item }}" + enabled: yes + daemon_reload: yes + loop: + - "{{ service }}.target" + - "{{ service }}-web.service" + - "{{ service }}-sidekiq.service" + - "{{ service }}-streaming.service" + +- name: Start services + service: + name: "{{ service }}.target" + state: started + +- name: Check if SSL certificate is present and register result + stat: + path: "/etc/letsencrypt/live/{{ domains |first }}/fullchain.pem" + register: ssl + +#- name: Generate certificate only if required (first time) + #block: + #- name: Template vhost without SSL for successfull LE challengce + #template: + #src: "vhost.j2" + #dest: "/etc/nginx/sites-available/{{ service }}" + #- name: Enable temporary nginx vhost for LE + #file: + #src: "/etc/nginx/sites-available/{{ service }}" + #dest: "/etc/nginx/sites-enabled/{{ service }}" + #state: link + #- name: Reload nginx conf + #service: + #name: nginx + #state: reloaded + #- name: Generate certificate with certbot + #shell: certbot certonly --webroot --webroot-path /var/lib/letsencrypt -d {{ domains |first }} + #when: ssl.stat.exists == false + +#- name: (Re)template conf file for nginx vhost with SSL + #template: + #src: "vhost.j2" + #dest: "/etc/nginx/sites-available/{{ service }}" + +#- name: Enable nginx vhost for mastodon + #file: + #src: "/etc/nginx/sites-available/{{ service }}" + #dest: "/etc/nginx/sites-enabled/{{ service }}" + #state: link + +#- name: Reload nginx conf + #service: + #name: nginx + #state: reloaded diff --git a/webapps/mastodon/tasks/upgrade.yml b/webapps/mastodon/tasks/upgrade.yml new file mode 100644 index 00000000..74959d3e --- /dev/null +++ b/webapps/mastodon/tasks/upgrade.yml @@ -0,0 +1,80 @@ +--- +# tasks file for mastodon + +- name: Dump database to a file with compression + postgresql_db: + name: "{{ service }}_production" + state: dump + target: "{{ service }}_production.sql.gz" + become_user: postgres + +- name: Checkout (git) + git: + repo: "{{ git_url }}" + dest: "~/mastodon/" + version: "{{ git_version | default(omit) }}" + #force: yes + update: yes + become_user: "{{ service }}" + +- block: + - name: Install bundler + shell: ". ~/.profile && gem install bundler --no-document" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Install gem dependencies + shell: ". ~/.profile && bundle install --deployment --without development test -j$(getconf _NPROCESSORS_ONLN)" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Install javascript dependencies + shell: ". ~/.profile && yarn install --pure-lockfile" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Run database migrations, skipping post-deployment + shell: ". ~/.profile && SKIP_POST_DEPLOYMENT_MIGRATIONS=true RAILS_ENV=production bundle exec rails db:migrate" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + - name: Precompile assets + shell: ". ~/.profile && RAILS_ENV=production bundle exec rails assets:precompile" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + become_user: "{{ service }}" + +- name: Restart services + service: + name: "{{ service }}.target" + state: restarted + +- name: Run database migrations, this time including post-deployment + shell: ". ~/.profile && SKIP_POST_DEPLOYMENT_MIGRATIONS=true RAILS_ENV=production bundle exec rails db:migrate" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh + become_user: "{{ service }}" + +- name: Define variable to skip next task by default + set_fact: + keep_db_dump: true + +- name: Remove database dump + file: + path: "{{ service }}_production.sql.gz" + state: absent + become_user: postgres + when: keep_db_dump is undefined + tags: clean + +- name: Template conf file for nginx vhost + template: + src: "vhost.j2" + dest: "/etc/nginx/sites-available/{{ service }}" + +- name: Reload nginx conf + service: + name: nginx + state: reloaded diff --git a/webapps/mastodon/templates/env.j2 b/webapps/mastodon/templates/env.j2 new file mode 100644 index 00000000..69fe5cd9 --- /dev/null +++ b/webapps/mastodon/templates/env.j2 @@ -0,0 +1,235 @@ +# Service dependencies +# You may set REDIS_URL instead for more advanced options +# You may also set REDIS_NAMESPACE to share Redis between multiple Mastodon servers +#REDIS_URL=unix:///var/run/redis/redis.sock +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_PASSWORD= +REDIS_NAMESPACE={{ service }} +# You may set DATABASE_URL instead for more advanced options +DB_HOST={{ db_host }} +DB_USER={{ db_user }} +DB_NAME={{ db_name }} +DB_PASS='{{ db_password }}' +DB_PORT=5432 +# Optional ElasticSearch configuration +#ES_ENABLED={{ app_es_enabled | default('false') }} +#ES_HOST={{ app_es_host | default('localhost') }} +#ES_PORT={{ app_es_port | default('9200') }} + +# Federation +# Note: Changing LOCAL_DOMAIN at a later time will cause unwanted side effects, including breaking all existing federation. +# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com. +LOCAL_DOMAIN={{ domains |first }} + +# Changing LOCAL_HTTPS in production is no longer supported. (Mastodon will always serve https:// links) + +# Use this only if you need to run mastodon on a different domain than the one used for federation. +# You can read more about this option on https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Serving_a_different_domain.md +# DO *NOT* USE THIS UNLESS YOU KNOW *EXACTLY* WHAT YOU ARE DOING. +# WEB_DOMAIN=mastodon.example.com + +# Use this if you want to have several aliases handler@example1.com +# handler@example2.com etc. for the same user. LOCAL_DOMAIN should not +# be added. Comma separated values +# ALTERNATE_DOMAINS=example1.com,example2.com + +# Application secrets +# Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose) +SECRET_KEY_BASE={{ app_secret_key_base }} +OTP_SECRET={{ app_otp_secret }} + +# VAPID keys (used for push notifications +# You can generate the keys using the following command (first is the private key, second is the public one) +# You should only generate this once per instance. If you later decide to change it, all push subscription will +# be invalidated, requiring the users to access the website again to resubscribe. +# +# Generate with `RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose) +# +# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html +VAPID_PRIVATE_KEY={{ app_vapid_private_key }} +VAPID_PUBLIC_KEY={{ app_vapid_public_key }} + +# Registrations +# Single user mode will disable registrations and redirect frontpage to the first profile +# SINGLE_USER_MODE=true +# Prevent registrations with following e-mail domains +# EMAIL_DOMAIN_BLACKLIST=example1.com|example2.de|etc +# Only allow registrations with the following e-mail domains +# EMAIL_DOMAIN_WHITELIST=example1.com|example2.de|etc + +# Optionally change default language +# DEFAULT_LOCALE=de + +# E-mail configuration +# Note: Mailgun and SparkPost (https://sparkpo.st/smtp) each have good free tiers +# If you want to use an SMTP server without authentication (e.g local Postfix relay) +# then set SMTP_AUTH_METHOD and SMTP_OPENSSL_VERIFY_MODE to 'none' and +# *comment* SMTP_LOGIN and SMTP_PASSWORD (leaving them blank is not enough). +SMTP_SERVER={{ app_smtp_server | default('smtp.mailgun.org') }} +SMTP_PORT={{ app_smtp_port | default('587') }} +#SMTP_LOGIN= +#SMTP_PASSWORD= +SMTP_FROM_ADDRESS={{ app_smtp_from_address | default('notifications@example.com') }} +#SMTP_DOMAIN= # defaults to LOCAL_DOMAIN +#SMTP_DELIVERY_METHOD=smtp # delivery method can also be sendmail +SMTP_AUTH_METHOD={{ app_smtp_auth_method | default('plain') }} +#SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt +#SMTP_OPENSSL_VERIFY_MODE={{ app_smtp_openssl_verify_mode | default('peer') }} +#SMTP_ENABLE_STARTTLS_AUTO=true +#SMTP_TLS=true + +# Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files. +# PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system +# PAPERCLIP_ROOT_URL=/system + +# Optional asset host for multi-server setups +# The asset host must allow cross origin request from WEB_DOMAIN or LOCAL_DOMAIN +# if WEB_DOMAIN is not set. For example, the server may have the +# following header field: +# Access-Control-Allow-Origin: https://example.com/ +# CDN_HOST=https://assets.example.com + +# S3 (optional) +# The attachment host must allow cross origin request from WEB_DOMAIN or +# LOCAL_DOMAIN if WEB_DOMAIN is not set. For example, the server may have the +# following header field: +# Access-Control-Allow-Origin: https://192.168.1.123:9000/ +# S3_ENABLED=true +# S3_BUCKET= +# AWS_ACCESS_KEY_ID= +# AWS_SECRET_ACCESS_KEY= +# S3_REGION= +# S3_PROTOCOL=http +# S3_HOSTNAME=192.168.1.123:9000 + +# S3 (Minio Config (optional) Please check Minio instance for details) +# The attachment host must allow cross origin request - see the description +# above. +# S3_ENABLED=true +# S3_BUCKET= +# AWS_ACCESS_KEY_ID= +# AWS_SECRET_ACCESS_KEY= +# S3_REGION= +# S3_PROTOCOL=https +# S3_HOSTNAME= +# S3_ENDPOINT= +# S3_SIGNATURE_VERSION= + +# Swift (optional) +# The attachment host must allow cross origin request - see the description +# above. +# SWIFT_ENABLED=true +# SWIFT_USERNAME= +# For Keystone V3, the value for SWIFT_TENANT should be the project name +# SWIFT_TENANT= +# SWIFT_PASSWORD= +# Some OpenStack V3 providers require PROJECT_ID (optional) +# SWIFT_PROJECT_ID= +# Keystone V2 and V3 URLs are supported. Use a V3 URL if possible to avoid +# issues with token rate-limiting during high load. +# SWIFT_AUTH_URL= +# SWIFT_CONTAINER= +# SWIFT_OBJECT_URL= +# SWIFT_REGION= +# Defaults to 'default' +# SWIFT_DOMAIN_NAME= +# Defaults to 60 seconds. Set to 0 to disable +# SWIFT_CACHE_TTL= + +# Optional alias for S3 (e.g. to serve files on a custom domain, possibly using Cloudfront or Cloudflare) +# S3_ALIAS_HOST= + +# Streaming API integration +# STREAMING_API_BASE_URL= + +# Advanced settings +# If you need to use pgBouncer, you need to disable prepared statements: +# PREPARED_STATEMENTS=false + +# Cluster number setting for streaming API server. +# If you comment out following line, cluster number will be `numOfCpuCores - 1`. +STREAMING_CLUSTER_NUM=1 + +# Docker mastodon user +# If you use Docker, you may want to assign UID/GID manually. +# UID=1000 +# GID=1000 + +# LDAP authentication (optional) +# LDAP_ENABLED=true +# LDAP_HOST=localhost +# LDAP_PORT=389 +# LDAP_METHOD=simple_tls +# LDAP_BASE= +# LDAP_BIND_DN= +# LDAP_PASSWORD= +# LDAP_UID=cn +# LDAP_SEARCH_FILTER="%{uid}=%{email}" + +# PAM authentication (optional) +# PAM authentication uses for the email generation the "email" pam variable +# and optional as fallback PAM_DEFAULT_SUFFIX +# The pam environment variable "email" is provided by: +# https://github.com/devkral/pam_email_extractor +# PAM_ENABLED=true +# Fallback email domain for email address generation (LOCAL_DOMAIN by default) +# PAM_EMAIL_DOMAIN=example.com +# Name of the pam service (pam "auth" section is evaluated) +# PAM_DEFAULT_SERVICE=rpam +# Name of the pam service used for checking if an user can register (pam "account" section is evaluated) (nil (disabled) by default) +# PAM_CONTROLLED_SERVICE=rpam + +# Global OAuth settings (optional) : +# If you have only one strategy, you may want to enable this +# OAUTH_REDIRECT_AT_SIGN_IN=true + +# Optional CAS authentication (cf. omniauth-cas) : +# CAS_ENABLED=true +# CAS_URL=https://sso.myserver.com/ +# CAS_HOST=sso.myserver.com/ +# CAS_PORT=443 +# CAS_SSL=true +# CAS_VALIDATE_URL= +# CAS_CALLBACK_URL= +# CAS_LOGOUT_URL= +# CAS_LOGIN_URL= +# CAS_UID_FIELD='user' +# CAS_CA_PATH= +# CAS_DISABLE_SSL_VERIFICATION=false +# CAS_UID_KEY='user' +# CAS_NAME_KEY='name' +# CAS_EMAIL_KEY='email' +# CAS_NICKNAME_KEY='nickname' +# CAS_FIRST_NAME_KEY='firstname' +# CAS_LAST_NAME_KEY='lastname' +# CAS_LOCATION_KEY='location' +# CAS_IMAGE_KEY='image' +# CAS_PHONE_KEY='phone' + +# Optional SAML authentication (cf. omniauth-saml) +# SAML_ENABLED=true +# SAML_ACS_URL= +# SAML_ISSUER=http://localhost:3000/auth/auth/saml/callback +# SAML_IDP_SSO_TARGET_URL=https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO +# SAML_IDP_CERT= +# SAML_IDP_CERT_FINGERPRINT= +# SAML_NAME_IDENTIFIER_FORMAT= +# SAML_CERT= +# SAML_PRIVATE_KEY= +# SAML_SECURITY_WANT_ASSERTION_SIGNED=true +# SAML_SECURITY_WANT_ASSERTION_ENCRYPTED=true +# SAML_SECURITY_ASSUME_EMAIL_IS_VERIFIED=true +# SAML_ATTRIBUTES_STATEMENTS_UID="urn:oid:0.9.2342.19200300.100.1.1" +# SAML_ATTRIBUTES_STATEMENTS_EMAIL="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" +# SAML_ATTRIBUTES_STATEMENTS_FULL_NAME="urn:oid:2.16.840.1.113730.3.1.241" +# SAML_ATTRIBUTES_STATEMENTS_FIRST_NAME="urn:oid:2.5.4.42" +# SAML_ATTRIBUTES_STATEMENTS_LAST_NAME="urn:oid:2.5.4.4" +# SAML_UID_ATTRIBUTE="urn:oid:0.9.2342.19200300.100.1.1" +# SAML_ATTRIBUTES_STATEMENTS_VERIFIED= +# SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL= + +# Use HTTP proxy for outgoing request (optional) +# http_proxy=http://gateway.local:8118 +# Access control for hidden service. +# ALLOW_ACCESS_TO_HIDDEN_SERVICE=true diff --git a/webapps/mastodon/templates/mastodon-sidekiq.service.j2 b/webapps/mastodon/templates/mastodon-sidekiq.service.j2 new file mode 100644 index 00000000..c2909526 --- /dev/null +++ b/webapps/mastodon/templates/mastodon-sidekiq.service.j2 @@ -0,0 +1,23 @@ +[Unit] +Description=mastodon-sidekiq +After=network.target +PartOf={{service}}.target + +[Service] +Type=simple +User={{service}} +Group={{service}} +UMask=0027 +WorkingDirectory=/home/{{service}}/mastodon/ +Environment="RAILS_ENV=production" +Environment="RAILS_LOG_LEVEL=error" +Environment="DB_POOL=25" +Environment="MALLOC_ARENA_MAX=2" +Environment="LD_PRELOAD=libjemalloc.so" +ExecStart=/home/{{service}}/.rbenv/shims/bundle exec sidekiq -c 25 +TimeoutSec=15 +Restart=always +SyslogIdentifier=%p + +[Install] +WantedBy={{service}}.target diff --git a/webapps/mastodon/templates/mastodon-streaming.service.j2 b/webapps/mastodon/templates/mastodon-streaming.service.j2 new file mode 100644 index 00000000..859d7506 --- /dev/null +++ b/webapps/mastodon/templates/mastodon-streaming.service.j2 @@ -0,0 +1,21 @@ +[Unit] +Description=mastodon-streaming +After=network.target +PartOf={{service}}.target + +[Service] +Type=simple +User={{service}} +Group={{service}} +UMask=0027 +WorkingDirectory=/home/{{service}}/mastodon/ +Environment="NODE_ENV=production" +Environment="PORT={{ node_port | default('4000')}}" +Environment="STREAMING_CLUSTER_NUM=1" +ExecStart=/bin/bash -lc "node ./streaming" +TimeoutSec=15 +Restart=always +SyslogIdentifier=%p + +[Install] +WantedBy={{service}}.target diff --git a/webapps/mastodon/templates/mastodon-web.service.j2 b/webapps/mastodon/templates/mastodon-web.service.j2 new file mode 100644 index 00000000..5f249325 --- /dev/null +++ b/webapps/mastodon/templates/mastodon-web.service.j2 @@ -0,0 +1,23 @@ +[Unit] +Description=mastodon-web +After=network.target +PartOf={{service}}.target + +[Service] +Type=simple +User={{service}} +Group={{service}} +UMask=0027 +WorkingDirectory=/home/{{service}}/mastodon/ +Environment="RAILS_ENV=production" +Environment="PORT={{puma_port|default('3000')}}" +Environment="RAILS_LOG_LEVEL=warn" +Environment="LD_PRELOAD=libjemalloc.so" +ExecStart=/home/{{service}}/.rbenv/shims/bundle exec puma -C config/puma.rb +ExecReload=/bin/kill -SIGUSR1 $MAINPID +TimeoutSec=15 +Restart=always +SyslogIdentifier=%p + +[Install] +WantedBy={{service}}.target diff --git a/webapps/mastodon/templates/mastodon.target.j2 b/webapps/mastodon/templates/mastodon.target.j2 new file mode 100644 index 00000000..0eb5475a --- /dev/null +++ b/webapps/mastodon/templates/mastodon.target.j2 @@ -0,0 +1,8 @@ +[Unit] +Description=Mastodon Microblogging service +Wants=redis-server.service +After=redis-server.service +Requires={{ service }}-web.service {{ service }}-sidekiq.service {{ service }}-streaming.service + +[Install] +WantedBy=multi-user.target diff --git a/webapps/mastodon/templates/vhost.j2 b/webapps/mastodon/templates/vhost.j2 new file mode 100644 index 00000000..fc27c041 --- /dev/null +++ b/webapps/mastodon/templates/vhost.j2 @@ -0,0 +1,94 @@ +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + listen [::]:80; + server_name {{ domains |first }}; + include /etc/nginx/snippets/letsencrypt.conf; + {% if ssl.stat.exists %} + location / { return 301 https://$host$request_uri; } + {% endif %} +} + +{% if ssl.stat.exists %} +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name {{ domains |first }}; + + include /etc/nginx/ssl/{{ service }}.conf; + include /etc/nginx/snippets/letsencrypt.conf; + + # OCSP stapling + ssl_stapling on; + ssl_stapling_verify on; + + + keepalive_timeout 70; + sendfile on; + client_max_body_size 0; + + root /home/{{ service }}/mastodon/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; + + #add_header Strict-Transport-Security "max-age=31536000"; + #add_header Content-Security-Policy "style-src 'self' 'unsafe-inline'; script-src 'self'; object-src 'self'; img-src data: https:; media-src data: https:; connect-src 'self' wss://{{ domains |first }}; upgrade-insecure-requests"; + + 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 @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:{{puma_port|default('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:{{ node_port | default('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; +} +{% endif %} diff --git a/webapps/mastodon/tests/inventory b/webapps/mastodon/tests/inventory new file mode 100644 index 00000000..878877b0 --- /dev/null +++ b/webapps/mastodon/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/webapps/mastodon/tests/test.yml b/webapps/mastodon/tests/test.yml new file mode 100644 index 00000000..708aca84 --- /dev/null +++ b/webapps/mastodon/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - mastodon diff --git a/webapps/mastodon/vars/main.yml b/webapps/mastodon/vars/main.yml new file mode 100644 index 00000000..85eebfd2 --- /dev/null +++ b/webapps/mastodon/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for mastodon From 8b89be02fa9ac7c298c22d888788e51e581ddd4a Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Fri, 6 Jan 2023 10:48:56 -0500 Subject: [PATCH 2/9] README.md + LISEZMOI.md --- webapps/mastodon/LISEZMOI.md | 73 ++++++++++++++++++++++++++++++ webapps/mastodon/README.md | 28 ++++++------ webapps/mastodon/defaults/main.yml | 8 ++-- 3 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 webapps/mastodon/LISEZMOI.md diff --git a/webapps/mastodon/LISEZMOI.md b/webapps/mastodon/LISEZMOI.md new file mode 100644 index 00000000..4af11788 --- /dev/null +++ b/webapps/mastodon/LISEZMOI.md @@ -0,0 +1,73 @@ +mastodon +========= + +Ce rôle installe le serveur de Mastodon, une application de microblogage, libre et autohébergée. + +Notez qu'hormis le présent fichier LISEZMOI.md, tous les fichiers du rôle mastodon sont rédigés en anglais afin de suivre les conventions de la communauté Ansible, favoriser sa réutilisation et son amélioration, etc. Libre à vous cependant de faire appel à ce role dans un playbook rédigé principalement en français ou toute autre langue. + +Requis +------ + +... + +Variables du rôle +----------------- + +Plusieurs des valeurs par défaut dans defaults/main.yml doivent être changées soit directement dans defaults/main.yml ou mieux encore en les supplantant ailleurs, par exemple dans votre playbook (voir l'exemple ci-bas). + +Dépendances +------------ + +Ce rôle Ansible dépend des rôles suivants : + +- nodejs +- postgresql +- redis +- elasticsearch +- rbenv +- nginx +- certbot + +Exemple de playbook +------------------- + +``` +- name: "Déployer un serveur Mastodon" + hosts: + - all + vars: + # Supplanter ici les variables du rôle + domains: ['votre-vrai-domaine.org'] + service: 'mon-mastodon' + db_host: 'localhost' + db_user: "{{ service }}" + db_name: "{{ service }}" + db_password: 'zKEh-CHANGEZ-MOI-qIKc' + app_secret_key_base: "" + app_otp_secret: "" + app_vapid_private_key: "" + app_vapid_public_key: "" + app_smtp_from_address: "mastodon@votre-vrai-domaine.org" + + pre_tasks: + - name: "Installer les rôles systèmes" + roles: + - { role: nodejs, nodejs_apt_version: 'node_16.x', nodejs_install_yarn: True } + - { role: postgresql } + - { role: redis } + - { role: elasticsearch } + - { role: nginx } + - { role: certbot } + roles: + - { role: webapps/mastodon , tags: "mastodon" } +``` + +Licence +------- + +GPLv3 + +Infos sur l'auteur +------------------ + +Mathieu Gauthier-Pilote, administrateur de systèmes chez Evolix. diff --git a/webapps/mastodon/README.md b/webapps/mastodon/README.md index e12ef769..aa117386 100644 --- a/webapps/mastodon/README.md +++ b/webapps/mastodon/README.md @@ -1,7 +1,9 @@ -Role Name +mastodon ========= -Ce rôle installe le serveur de Mastodon, une application libre de microblogage, libre et autohébergée. +This role installs or upgrades the server for Mastodon, a free and decentralized microblogging social network. + +FRENCH: Voir le fichier LISEZMOI.md pour le français. Requirements ------------ @@ -11,12 +13,12 @@ Requirements Role Variables -------------- -Plusieurs des valeurs par défaut dans defaults/main.yml doivent être changées soit directement dans defaults/main.yml ou mieux encore en les supplantant ailleurs, par exemple dans votre playbook (voir l'exemple ci-bas). +Several of the default values in defaults/main.yml must be changed either directly in defaults/main.yml or better even by overwriting them somewhere else, for example in your playbook (see the example below). Dependencies ------------ -Ce rôle Ansible dépend des rôles suivants : +This Ansible role depends on the following other roles: - nodejs - postgresql @@ -30,25 +32,25 @@ Example Playbook ---------------- ``` -- name: "Déployer un serveur Mastodon" +- name: "Deploy a Mastodon server" hosts: - all vars: - # Supplanter ici les variables du rôle - domains: ['votre-vrai-domaine.org'] - service: 'mon-mastodon' + # Overwrite the role variable here + domains: ['your-real-domain.org'] + service: 'my-mastodon' db_host: 'localhost' db_user: "{{ service }}" db_name: "{{ service }}" - db_password: 'zKEh-CHANGEZ-MOI-qIKc' + db_password: 'zKEh-CHANGE-ME-qIKc' app_secret_key_base: "" app_otp_secret: "" app_vapid_private_key: "" app_vapid_public_key: "" - app_smtp_from_address: "mastodon@votre-vrai-domaine.org" + app_smtp_from_address: "mastodon@your-real-domain.org" pre_tasks: - - name: "Installer les rôles systèmes" + - name: "Install system roles" roles: - { role: nodejs, nodejs_apt_version: 'node_16.x', nodejs_install_yarn: True } - { role: postgresql } @@ -63,9 +65,9 @@ Example Playbook License ------- -BSD +GPLv3 Author Information ------------------ -Mathieu Gauthier-Pilote, administrateur de systèmes chez Evolix. +Mathieu Gauthier-Pilote, sys. admin. at Evolix. diff --git a/webapps/mastodon/defaults/main.yml b/webapps/mastodon/defaults/main.yml index d5b82550..9f683292 100644 --- a/webapps/mastodon/defaults/main.yml +++ b/webapps/mastodon/defaults/main.yml @@ -1,16 +1,18 @@ --- # defaults file for mastodon system_dep: "['imagemagick', 'ffmpeg', 'libpq-dev', 'libxml2-dev', 'libxslt1-dev', 'file', 'git-core', 'g++', 'libprotobuf-dev', 'protobuf-compiler', 'pkg-config', 'nodejs', 'gcc', 'autoconf', 'bison', 'build-essential', 'libssl-dev', 'libyaml-dev', 'libreadline6-dev', 'zlib1g-dev', 'libncurses5-dev', 'libffi-dev', 'libgdbm-dev', 'nginx', 'redis-server', 'redis-tools', 'postgresql', 'postgresql-contrib', 'certbot', 'python3-certbot-nginx', 'libidn11-dev', 'libicu-dev', 'libjemalloc-dev', 'yarn']" -domains: ['exemple.evolix.org'] +domains: ['example.somedomain.org'] git_url: 'https://github.com/mastodon/mastodon.git' git_version: 'v4.0.2' ruby_version: '3.0.4' -service: 'exemple' +service: 'example' db_host: 'localhost' db_user: "{{ service }}" db_name: "{{ service }}_production" db_password: 'CHANGE_ME' +#puma_port: '3000' +#node_port: '4000' app_secret_key_base: "" app_otp_secret: "" @@ -18,7 +20,7 @@ app_vapid_private_key: "" app_vapid_public_key: "" app_smtp_server: "127.0.0.1" app_smtp_port: "25" -app_smtp_from_address: "exemple@evolix.org" +app_smtp_from_address: "example@somedomain.org" app_smtp_auth_method: "none" app_smtp_openssl_verify_mode: "none" app_es_enabled: "false" From c09fe9605b663c544eb0692afb1113b723c4207b Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Thu, 12 Jan 2023 16:27:00 -0500 Subject: [PATCH 3/9] Install LE cert. when there is none --- webapps/mastodon/tasks/main.yml | 67 ++++++++++++++++------------- webapps/mastodon/templates/vhost.j2 | 4 +- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/webapps/mastodon/tasks/main.yml b/webapps/mastodon/tasks/main.yml index fed52d83..bcd8f887 100644 --- a/webapps/mastodon/tasks/main.yml +++ b/webapps/mastodon/tasks/main.yml @@ -174,37 +174,42 @@ path: "/etc/letsencrypt/live/{{ domains |first }}/fullchain.pem" register: ssl -#- name: Generate certificate only if required (first time) - #block: - #- name: Template vhost without SSL for successfull LE challengce - #template: - #src: "vhost.j2" - #dest: "/etc/nginx/sites-available/{{ service }}" - #- name: Enable temporary nginx vhost for LE - #file: - #src: "/etc/nginx/sites-available/{{ service }}" - #dest: "/etc/nginx/sites-enabled/{{ service }}" - #state: link - #- name: Reload nginx conf - #service: - #name: nginx - #state: reloaded - #- name: Generate certificate with certbot - #shell: certbot certonly --webroot --webroot-path /var/lib/letsencrypt -d {{ domains |first }} - #when: ssl.stat.exists == false +- name: Generate certificate only if required (first time) + block: + - name: Template vhost without SSL for successfull LE challengce + template: + src: "vhost.j2" + dest: "/etc/nginx/sites-available/{{ service }}" + - name: Enable temporary nginx vhost for LE + file: + src: "/etc/nginx/sites-available/{{ service }}" + dest: "/etc/nginx/sites-enabled/{{ service }}" + state: link + - name: Reload nginx conf + service: + name: nginx + state: reloaded + - name: Generate certificate with certbot + shell: certbot certonly --webroot --webroot-path /var/lib/letsencrypt -d {{ domains |first }} + when: ssl.stat.exists == false -#- name: (Re)template conf file for nginx vhost with SSL - #template: - #src: "vhost.j2" - #dest: "/etc/nginx/sites-available/{{ service }}" +- name: (Re)check if SSL certificate is present and register result + stat: + path: "/etc/letsencrypt/live/{{ domains |first }}/fullchain.pem" + register: ssl -#- name: Enable nginx vhost for mastodon - #file: - #src: "/etc/nginx/sites-available/{{ service }}" - #dest: "/etc/nginx/sites-enabled/{{ service }}" - #state: link +- name: (Re)template conf file for nginx vhost with SSL + template: + src: "vhost.j2" + dest: "/etc/nginx/sites-available/{{ service }}" -#- name: Reload nginx conf - #service: - #name: nginx - #state: reloaded +- name: Enable nginx vhost for mastodon + file: + src: "/etc/nginx/sites-available/{{ service }}" + dest: "/etc/nginx/sites-enabled/{{ service }}" + state: link + +- name: Reload nginx conf + service: + name: nginx + state: reloaded diff --git a/webapps/mastodon/templates/vhost.j2 b/webapps/mastodon/templates/vhost.j2 index fc27c041..673cb186 100644 --- a/webapps/mastodon/templates/vhost.j2 +++ b/webapps/mastodon/templates/vhost.j2 @@ -19,8 +19,10 @@ server { listen [::]:443 ssl http2; server_name {{ domains |first }}; - include /etc/nginx/ssl/{{ service }}.conf; include /etc/nginx/snippets/letsencrypt.conf; + ssl_certificate /etc/letsencrypt/live/{{ domains |first }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ domains |first }}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{{ domains |first }}/chain.pem; # OCSP stapling ssl_stapling on; From d8a7a439b2ff096db91b1ee6c2b773561aeed50d Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Fri, 13 Jan 2023 10:26:48 -0500 Subject: [PATCH 4/9] Allow nginx to read public assets --- webapps/mastodon/tasks/main.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/webapps/mastodon/tasks/main.yml b/webapps/mastodon/tasks/main.yml index bcd8f887..cecbc9ba 100644 --- a/webapps/mastodon/tasks/main.yml +++ b/webapps/mastodon/tasks/main.yml @@ -32,6 +32,7 @@ version: "{{ git_version | default(omit) }}" #force: yes update: yes + umask: '0022' become_user: "{{ service }}" - block: @@ -133,6 +134,14 @@ executable: /bin/bash # fails with /bin/sh become_user: "{{ service }}" +- name: Adjust permissions of files in public folder + file: + path: "~/mastodon/public" + state: directory + mode: 'o=rX' + recurse: true + become_user: "{{ service }}" + - name: Add systemd target template: src: "mastodon.target.j2" From e2ab83dbfad4626d128e488003b5fb85fabbcdaf Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Mon, 16 Jan 2023 09:23:16 -0500 Subject: [PATCH 5/9] Ajust permissions of files in public folder --- webapps/mastodon/tasks/upgrade.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/webapps/mastodon/tasks/upgrade.yml b/webapps/mastodon/tasks/upgrade.yml index 74959d3e..c2840963 100644 --- a/webapps/mastodon/tasks/upgrade.yml +++ b/webapps/mastodon/tasks/upgrade.yml @@ -43,6 +43,12 @@ args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh + - name: Adjust permissions of files in public folder + file: + path: "~/mastodon/public" + state: directory + mode: 'o=rX' + recurse: true become_user: "{{ service }}" - name: Restart services From a03ed08b4a48adb6cef778c0325f0ebc1873ccb0 Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Mon, 16 Jan 2023 10:42:41 -0500 Subject: [PATCH 6/9] use ansible_processor_count + fix db dump path --- webapps/mastodon/tasks/main.yml | 4 ++-- webapps/mastodon/tasks/upgrade.yml | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/webapps/mastodon/tasks/main.yml b/webapps/mastodon/tasks/main.yml index cecbc9ba..b2f273de 100644 --- a/webapps/mastodon/tasks/main.yml +++ b/webapps/mastodon/tasks/main.yml @@ -1,5 +1,5 @@ --- -# tasks file for mastodon +# tasks file for mastodon install - name: Install main system dependencies apt: @@ -42,7 +42,7 @@ chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Install gem dependencies - shell: ". ~/.profile && bundle install --deployment --without development test -j$(getconf _NPROCESSORS_ONLN)" + shell: ". ~/.profile && bundle install --deployment --without development test -j{{ ansible_processor_count }}" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh diff --git a/webapps/mastodon/tasks/upgrade.yml b/webapps/mastodon/tasks/upgrade.yml index c2840963..e0644c66 100644 --- a/webapps/mastodon/tasks/upgrade.yml +++ b/webapps/mastodon/tasks/upgrade.yml @@ -1,11 +1,11 @@ --- -# tasks file for mastodon +# tasks file for mastodon upgrade - name: Dump database to a file with compression postgresql_db: name: "{{ service }}_production" state: dump - target: "{{ service }}_production.sql.gz" + target: "~/{{ service }}_production.sql.gz" become_user: postgres - name: Checkout (git) @@ -24,7 +24,7 @@ chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Install gem dependencies - shell: ". ~/.profile && bundle install --deployment --without development test -j$(getconf _NPROCESSORS_ONLN)" + shell: ". ~/.profile && bundle install --deployment --without development test -j{{ ansible_processor_count }}" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh @@ -63,23 +63,23 @@ executable: /bin/bash # fails with /bin/sh become_user: "{{ service }}" +- name: Restart services + service: + name: "{{ service }}.target" + state: restarted + - name: Define variable to skip next task by default set_fact: keep_db_dump: true - name: Remove database dump file: - path: "{{ service }}_production.sql.gz" + path: "~/{{ service }}_production.sql.gz" state: absent become_user: postgres when: keep_db_dump is undefined tags: clean -- name: Template conf file for nginx vhost - template: - src: "vhost.j2" - dest: "/etc/nginx/sites-available/{{ service }}" - - name: Reload nginx conf service: name: nginx From 98d2ece11c43ae65ae562e62a23a0b116d1f97ac Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Thu, 6 Apr 2023 14:46:01 -0400 Subject: [PATCH 7/9] With post-deployement the 2nd time; allow to upgrade rbenv if needed; upgrade browsers list db to remove warnings --- webapps/mastodon/tasks/upgrade.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/webapps/mastodon/tasks/upgrade.yml b/webapps/mastodon/tasks/upgrade.yml index e0644c66..d1b8c57a 100644 --- a/webapps/mastodon/tasks/upgrade.yml +++ b/webapps/mastodon/tasks/upgrade.yml @@ -8,12 +8,19 @@ target: "~/{{ service }}_production.sql.gz" become_user: postgres +- name: Install Ruby for service user (rbenv) + include_role: + name: rbenv + vars: + - username: "{{ service }}" + - rbenv_ruby_version: "{{ ruby_version }}" + - name: Checkout (git) git: repo: "{{ git_url }}" dest: "~/mastodon/" version: "{{ git_version | default(omit) }}" - #force: yes + force: yes update: yes become_user: "{{ service }}" @@ -33,6 +40,11 @@ args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh + - name: Upgrade browsers list db + shell: ". ~/.profile && npx update-browserslist-db@latest" + args: + chdir: "~/mastodon" + executable: /bin/bash # fails with /bin/sh - name: Run database migrations, skipping post-deployment shell: ". ~/.profile && SKIP_POST_DEPLOYMENT_MIGRATIONS=true RAILS_ENV=production bundle exec rails db:migrate" args: @@ -57,7 +69,7 @@ state: restarted - name: Run database migrations, this time including post-deployment - shell: ". ~/.profile && SKIP_POST_DEPLOYMENT_MIGRATIONS=true RAILS_ENV=production bundle exec rails db:migrate" + shell: ". ~/.profile && RAILS_ENV=production bundle exec rails db:migrate" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh From f061bb6f644f9a3b57601bae866b1020ec33bafc Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Thu, 23 May 2024 16:41:11 -0400 Subject: [PATCH 8/9] mastodon_ prefix for role vars --- webapps/mastodon/LISEZMOI.md | 28 +++--- webapps/mastodon/README.md | 28 +++--- webapps/mastodon/defaults/main.yml | 42 ++++---- webapps/mastodon/tasks/main.yml | 99 +++++++++++-------- webapps/mastodon/templates/env.j2 | 36 +++---- .../templates/mastodon-sidekiq.service.j2 | 12 +-- .../templates/mastodon-streaming.service.j2 | 12 +-- .../templates/mastodon-web.service.j2 | 14 +-- webapps/mastodon/templates/mastodon.target.j2 | 2 +- webapps/mastodon/templates/vhost.j2 | 18 ++-- 10 files changed, 149 insertions(+), 142 deletions(-) diff --git a/webapps/mastodon/LISEZMOI.md b/webapps/mastodon/LISEZMOI.md index 4af11788..6002a203 100644 --- a/webapps/mastodon/LISEZMOI.md +++ b/webapps/mastodon/LISEZMOI.md @@ -20,13 +20,7 @@ Dépendances Ce rôle Ansible dépend des rôles suivants : -- nodejs -- postgresql -- redis -- elasticsearch - rbenv -- nginx -- certbot Exemple de playbook ------------------- @@ -37,17 +31,17 @@ Exemple de playbook - all vars: # Supplanter ici les variables du rôle - domains: ['votre-vrai-domaine.org'] - service: 'mon-mastodon' - db_host: 'localhost' - db_user: "{{ service }}" - db_name: "{{ service }}" - db_password: 'zKEh-CHANGEZ-MOI-qIKc' - app_secret_key_base: "" - app_otp_secret: "" - app_vapid_private_key: "" - app_vapid_public_key: "" - app_smtp_from_address: "mastodon@votre-vrai-domaine.org" + mastodon_domains: ['votre-vrai-domaine.org'] + mastodon_service: 'mon-mastodon' + mastodon_db_host: 'localhost' + mastodon_db_user: "{{ service }}" + mastodon_db_name: "{{ service }}" + mastodon_db_password: 'zKEh-CHANGEZ-MOI-qIKc' + mastodon_app_secret_key_base: "" + mastodon_app_otp_secret: "" + mastodon_app_vapid_private_key: "" + mastodon_app_vapid_public_key: "" + mastodon_app_smtp_from_address: "mastodon@votre-vrai-domaine.org" pre_tasks: - name: "Installer les rôles systèmes" diff --git a/webapps/mastodon/README.md b/webapps/mastodon/README.md index aa117386..249322b0 100644 --- a/webapps/mastodon/README.md +++ b/webapps/mastodon/README.md @@ -20,13 +20,7 @@ Dependencies This Ansible role depends on the following other roles: -- nodejs -- postgresql -- redis -- elasticsearch - rbenv -- nginx -- certbot Example Playbook ---------------- @@ -37,17 +31,17 @@ Example Playbook - all vars: # Overwrite the role variable here - domains: ['your-real-domain.org'] - service: 'my-mastodon' - db_host: 'localhost' - db_user: "{{ service }}" - db_name: "{{ service }}" - db_password: 'zKEh-CHANGE-ME-qIKc' - app_secret_key_base: "" - app_otp_secret: "" - app_vapid_private_key: "" - app_vapid_public_key: "" - app_smtp_from_address: "mastodon@your-real-domain.org" + mastodon_domains: ['your-real-domain.org'] + mastodon_service: 'my-mastodon' + mastodon_db_host: 'localhost' + mastodon_db_user: "{{ service }}" + mastodon_db_name: "{{ service }}" + mastodon_db_password: 'zKEh-CHANGE-ME-qIKc' + mastodon_app_secret_key_base: "" + mastodon_app_otp_secret: "" + mastodon_app_vapid_private_key: "" + mastodon_app_vapid_public_key: "" + mastodon_app_smtp_from_address: "mastodon@your-real-domain.org" pre_tasks: - name: "Install system roles" diff --git a/webapps/mastodon/defaults/main.yml b/webapps/mastodon/defaults/main.yml index 9f683292..68667691 100644 --- a/webapps/mastodon/defaults/main.yml +++ b/webapps/mastodon/defaults/main.yml @@ -1,26 +1,24 @@ --- # defaults file for mastodon -system_dep: "['imagemagick', 'ffmpeg', 'libpq-dev', 'libxml2-dev', 'libxslt1-dev', 'file', 'git-core', 'g++', 'libprotobuf-dev', 'protobuf-compiler', 'pkg-config', 'nodejs', 'gcc', 'autoconf', 'bison', 'build-essential', 'libssl-dev', 'libyaml-dev', 'libreadline6-dev', 'zlib1g-dev', 'libncurses5-dev', 'libffi-dev', 'libgdbm-dev', 'nginx', 'redis-server', 'redis-tools', 'postgresql', 'postgresql-contrib', 'certbot', 'python3-certbot-nginx', 'libidn11-dev', 'libicu-dev', 'libjemalloc-dev', 'yarn']" -domains: ['example.somedomain.org'] -git_url: 'https://github.com/mastodon/mastodon.git' -git_version: 'v4.0.2' -ruby_version: '3.0.4' -service: 'example' +mastodon_system_dep: "['imagemagick', 'ffmpeg', 'libpq-dev', 'libxml2-dev', 'libxslt1-dev', 'file', 'git-core', 'g++', 'libprotobuf-dev', 'protobuf-compiler', 'pkg-config', 'nodejs', 'gcc', 'autoconf', 'bison', 'build-essential', 'libssl-dev', 'libyaml-dev', 'libreadline6-dev', 'zlib1g-dev', 'libncurses5-dev', 'libffi-dev', 'libgdbm-dev', 'nginx', 'redis-server', 'redis-tools', 'postgresql', 'postgresql-contrib', 'certbot', 'python3-certbot-nginx', 'python3-psycopg2', 'libidn11-dev', 'libicu-dev', 'libjemalloc-dev']" +mastodon_domains: ['example.somedomain.org'] +mastodon_git_url: 'https://github.com/mastodon/mastodon.git' +mastodon_git_version: 'v4.0.2' +mastodon_ruby_version: '3.0.4' +mastodon_service: 'example' -db_host: 'localhost' -db_user: "{{ service }}" -db_name: "{{ service }}_production" -db_password: 'CHANGE_ME' -#puma_port: '3000' -#node_port: '4000' +mastodon_db_host: 'localhost' +mastodon_db_user: "{{ mastodon_service }}" +mastodon_db_name: "{{ mastodon_service }}_production" +mastodon_db_password: 'CHANGE_ME' -app_secret_key_base: "" -app_otp_secret: "" -app_vapid_private_key: "" -app_vapid_public_key: "" -app_smtp_server: "127.0.0.1" -app_smtp_port: "25" -app_smtp_from_address: "example@somedomain.org" -app_smtp_auth_method: "none" -app_smtp_openssl_verify_mode: "none" -app_es_enabled: "false" +mastodon_app_secret_key_base: "" +mastodon_app_otp_secret: "" +mastodon_app_vapid_private_key: "" +mastodon_app_vapid_public_key: "" +mastodon_app_smtp_server: "127.0.0.1" +mastodon_app_smtp_port: "25" +mastodon_app_smtp_from_address: "example@somedomain.org" +mastodon_app_smtp_auth_method: "none" +mastodon_app_smtp_openssl_verify_mode: "none" +mastodon_app_es_enabled: "false" diff --git a/webapps/mastodon/tasks/main.yml b/webapps/mastodon/tasks/main.yml index b2f273de..d08f306f 100644 --- a/webapps/mastodon/tasks/main.yml +++ b/webapps/mastodon/tasks/main.yml @@ -3,18 +3,39 @@ - name: Install main system dependencies apt: - name: "{{ system_dep }}" + name: "{{ mastodon_system_dep }}" + update_cache: yes + +- name: Install npm on Debian 12 + apt: + name: npm + when: ansible_distribution_major_version is version('12', '>=') + +- name: Install corepack via npm on Debian 12 + shell: npm install -g corepack + when: ansible_distribution_major_version is version('12', '>=') + +- name: Fix permissions for corepack + ansible.builtin.file: + path: /usr/local/lib/node_modules/ + state: directory + mode: o+rx + recurse: yes + when: ansible_distribution_major_version is version('12', '>=') + +- name: Enable yarn (via corepack) + shell: "corepack enable; yarn set version classic" - name: Add PostgreSQL user postgresql_user: - name: "{{ db_user }}" - password: "{{ db_password }}" + name: "{{ mastodon_db_user }}" + password: "{{ mastodon_db_password }}" role_attr_flags: CREATEDB become_user: postgres - name: Add UNIX account user: - name: "{{ service }}" + name: "{{ mastodon_service }}" shell: /bin/bash # umask: "0022" nécessite ansible-core 2.12 @@ -22,18 +43,18 @@ include_role: name: rbenv vars: - - username: "{{ service }}" - - rbenv_ruby_version: "{{ ruby_version }}" + - username: "{{ mastodon_service }}" + - rbenv_ruby_version: "{{ mastodon_ruby_version }}" - name: Clone Mastodon repo (git) git: - repo: "{{ git_url }}" + repo: "{{ mastodon_git_url }}" dest: "~/mastodon/" - version: "{{ git_version | default(omit) }}" + version: "{{ mastodon_git_version | default(omit) }}" #force: yes update: yes umask: '0022' - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" - block: - name: Install bundler @@ -51,21 +72,21 @@ args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" - name: Template .env.production configuration file template: src: "env.j2" - dest: "~{{ service }}/mastodon/.env.production" - owner: "{{ service }}" - group: "{{ service }}" + dest: "~{{ mastodon_service }}/mastodon/.env.production" + owner: "{{ mastodon_service }}" + group: "{{ mastodon_service }}" mode: "0640" - name: Check if secrets need to be generated or not shell: "grep -P SECRET_KEY_BASE=[[:alnum:]]{128} .env.production" args: chdir: "~/mastodon" - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" register: secrets failed_when: "secrets.rc == 2" @@ -103,18 +124,18 @@ lineinfile: path: "~/mastodon/.env.production" regexp: '^VAPID_PRIVATE_KEY=' - line: "VAPID_PRIVATE_KEY={{ app_vapid_private_key.stdout }}" + line: "VAPID_PRIVATE_KEY={{ mastodon_app_vapid_private_key.stdout }}" - name: Write app_vapid_public_key to production .env file lineinfile: path: "~/mastodon/.env.production" regexp: '^VAPID_PUBLIC_KEY=' - line: "VAPID_PUBLIC_KEY={{ app_vapid_public_key.stdout }}" - become_user: "{{ service }}" + line: "VAPID_PUBLIC_KEY={{ mastodon_app_vapid_public_key.stdout }}" + become_user: "{{ mastodon_service }}" when: "secrets.rc == 1" - name: Check if mastodon database is already present or not shell: | - psql -lqt | cut -d \| -f 1 | grep -qw {{ service }}_production + psql -lqt | cut -d \| -f 1 | grep -qw {{ mastodon_service }}_production become_user: postgres register: db_present failed_when: "db_present.rc == 2" @@ -124,7 +145,7 @@ args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" when: "db_present.rc == 1" - name: Precompile assets @@ -132,7 +153,7 @@ args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" - name: Adjust permissions of files in public folder file: @@ -140,27 +161,27 @@ state: directory mode: 'o=rX' recurse: true - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" - name: Add systemd target template: src: "mastodon.target.j2" - dest: "/etc/systemd/system/{{ service }}.target" + dest: "/etc/systemd/system/{{ mastodon_service }}.target" - name: Add systemd web unit template: src: "mastodon-web.service.j2" - dest: "/etc/systemd/system/{{ service }}-web.service" + dest: "/etc/systemd/system/{{ mastodon_service }}-web.service" - name: Add systemd sidekiq unit template: src: "mastodon-sidekiq.service.j2" - dest: "/etc/systemd/system/{{ service }}-sidekiq.service" + dest: "/etc/systemd/system/{{ mastodon_service }}-sidekiq.service" - name: Add systemd streaming unit template: src: "mastodon-streaming.service.j2" - dest: "/etc/systemd/system/{{ service }}-streaming.service" + dest: "/etc/systemd/system/{{ mastodon_service }}-streaming.service" - name: Enable systemd units systemd: @@ -168,19 +189,19 @@ enabled: yes daemon_reload: yes loop: - - "{{ service }}.target" - - "{{ service }}-web.service" - - "{{ service }}-sidekiq.service" - - "{{ service }}-streaming.service" + - "{{ mastodon_service }}.target" + - "{{ mastodon_service }}-web.service" + - "{{ mastodon_service }}-sidekiq.service" + - "{{ mastodon_service }}-streaming.service" - name: Start services service: - name: "{{ service }}.target" + name: "{{ mastodon_service }}.target" state: started - name: Check if SSL certificate is present and register result stat: - path: "/etc/letsencrypt/live/{{ domains |first }}/fullchain.pem" + path: "/etc/letsencrypt/live/{{ mastodon_domains |first }}/fullchain.pem" register: ssl - name: Generate certificate only if required (first time) @@ -188,34 +209,34 @@ - name: Template vhost without SSL for successfull LE challengce template: src: "vhost.j2" - dest: "/etc/nginx/sites-available/{{ service }}" + dest: "/etc/nginx/sites-available/{{ mastodon_service }}" - name: Enable temporary nginx vhost for LE file: - src: "/etc/nginx/sites-available/{{ service }}" - dest: "/etc/nginx/sites-enabled/{{ service }}" + src: "/etc/nginx/sites-available/{{ mastodon_service }}" + dest: "/etc/nginx/sites-enabled/{{ mastodon_service }}" state: link - name: Reload nginx conf service: name: nginx state: reloaded - name: Generate certificate with certbot - shell: certbot certonly --webroot --webroot-path /var/lib/letsencrypt -d {{ domains |first }} + shell: certbot certonly --webroot --webroot-path /var/lib/letsencrypt -d {{ mastodon_domains |first }} when: ssl.stat.exists == false - name: (Re)check if SSL certificate is present and register result stat: - path: "/etc/letsencrypt/live/{{ domains |first }}/fullchain.pem" + path: "/etc/letsencrypt/live/{{ mastodon_domains |first }}/fullchain.pem" register: ssl - name: (Re)template conf file for nginx vhost with SSL template: src: "vhost.j2" - dest: "/etc/nginx/sites-available/{{ service }}" + dest: "/etc/nginx/sites-available/{{ mastodon_service }}" - name: Enable nginx vhost for mastodon file: - src: "/etc/nginx/sites-available/{{ service }}" - dest: "/etc/nginx/sites-enabled/{{ service }}" + src: "/etc/nginx/sites-available/{{ mastodon_service }}" + dest: "/etc/nginx/sites-enabled/{{ mastodon_service }}" state: link - name: Reload nginx conf diff --git a/webapps/mastodon/templates/env.j2 b/webapps/mastodon/templates/env.j2 index 69fe5cd9..0b6aec11 100644 --- a/webapps/mastodon/templates/env.j2 +++ b/webapps/mastodon/templates/env.j2 @@ -5,22 +5,22 @@ REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD= -REDIS_NAMESPACE={{ service }} +REDIS_NAMESPACE={{ mastodon_service }} # You may set DATABASE_URL instead for more advanced options -DB_HOST={{ db_host }} -DB_USER={{ db_user }} -DB_NAME={{ db_name }} -DB_PASS='{{ db_password }}' +DB_HOST={{ mastodon_db_host }} +DB_USER={{ mastodon_db_user }} +DB_NAME={{ mastodon_db_name }} +DB_PASS='{{ mastodon_db_password }}' DB_PORT=5432 # Optional ElasticSearch configuration -#ES_ENABLED={{ app_es_enabled | default('false') }} -#ES_HOST={{ app_es_host | default('localhost') }} -#ES_PORT={{ app_es_port | default('9200') }} +#ES_ENABLED={{ mastodon_app_es_enabled | default('false') }} +#ES_HOST={{ mastodon_app_es_host | default('localhost') }} +#ES_PORT={{ mastodon_app_es_port | default('9200') }} # Federation # Note: Changing LOCAL_DOMAIN at a later time will cause unwanted side effects, including breaking all existing federation. # LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com. -LOCAL_DOMAIN={{ domains |first }} +LOCAL_DOMAIN={{ mastodon_domains |first }} # Changing LOCAL_HTTPS in production is no longer supported. (Mastodon will always serve https:// links) @@ -36,8 +36,8 @@ LOCAL_DOMAIN={{ domains |first }} # Application secrets # Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose) -SECRET_KEY_BASE={{ app_secret_key_base }} -OTP_SECRET={{ app_otp_secret }} +SECRET_KEY_BASE={{ mastodon_app_secret_key_base }} +OTP_SECRET={{ mastodon_app_otp_secret }} # VAPID keys (used for push notifications # You can generate the keys using the following command (first is the private key, second is the public one) @@ -47,8 +47,8 @@ OTP_SECRET={{ app_otp_secret }} # Generate with `RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose) # # For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html -VAPID_PRIVATE_KEY={{ app_vapid_private_key }} -VAPID_PUBLIC_KEY={{ app_vapid_public_key }} +VAPID_PRIVATE_KEY={{ mastodon_app_vapid_private_key }} +VAPID_PUBLIC_KEY={{ mastodon_app_vapid_public_key }} # Registrations # Single user mode will disable registrations and redirect frontpage to the first profile @@ -66,16 +66,16 @@ VAPID_PUBLIC_KEY={{ app_vapid_public_key }} # If you want to use an SMTP server without authentication (e.g local Postfix relay) # then set SMTP_AUTH_METHOD and SMTP_OPENSSL_VERIFY_MODE to 'none' and # *comment* SMTP_LOGIN and SMTP_PASSWORD (leaving them blank is not enough). -SMTP_SERVER={{ app_smtp_server | default('smtp.mailgun.org') }} -SMTP_PORT={{ app_smtp_port | default('587') }} +SMTP_SERVER={{ mastodon_app_smtp_server | default('smtp.mailgun.org') }} +SMTP_PORT={{ mastodon_app_smtp_port | default('587') }} #SMTP_LOGIN= #SMTP_PASSWORD= -SMTP_FROM_ADDRESS={{ app_smtp_from_address | default('notifications@example.com') }} +SMTP_FROM_ADDRESS={{ mastodon_app_smtp_from_address | default('notifications@example.com') }} #SMTP_DOMAIN= # defaults to LOCAL_DOMAIN #SMTP_DELIVERY_METHOD=smtp # delivery method can also be sendmail -SMTP_AUTH_METHOD={{ app_smtp_auth_method | default('plain') }} +SMTP_AUTH_METHOD={{ mastodon_app_smtp_auth_method | default('plain') }} #SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt -#SMTP_OPENSSL_VERIFY_MODE={{ app_smtp_openssl_verify_mode | default('peer') }} +#SMTP_OPENSSL_VERIFY_MODE={{ mastodon_app_smtp_openssl_verify_mode | default('peer') }} #SMTP_ENABLE_STARTTLS_AUTO=true #SMTP_TLS=true diff --git a/webapps/mastodon/templates/mastodon-sidekiq.service.j2 b/webapps/mastodon/templates/mastodon-sidekiq.service.j2 index c2909526..62059bc4 100644 --- a/webapps/mastodon/templates/mastodon-sidekiq.service.j2 +++ b/webapps/mastodon/templates/mastodon-sidekiq.service.j2 @@ -1,23 +1,23 @@ [Unit] Description=mastodon-sidekiq After=network.target -PartOf={{service}}.target +PartOf={{ mastodon_service }}.target [Service] Type=simple -User={{service}} -Group={{service}} +User={{ mastodon_service }} +Group={{ mastodon_service }} UMask=0027 -WorkingDirectory=/home/{{service}}/mastodon/ +WorkingDirectory=/home/{{ mastodon_service }}/mastodon/ Environment="RAILS_ENV=production" Environment="RAILS_LOG_LEVEL=error" Environment="DB_POOL=25" Environment="MALLOC_ARENA_MAX=2" Environment="LD_PRELOAD=libjemalloc.so" -ExecStart=/home/{{service}}/.rbenv/shims/bundle exec sidekiq -c 25 +ExecStart=/home/{{ mastodon_service }}/.rbenv/shims/bundle exec sidekiq -c 25 TimeoutSec=15 Restart=always SyslogIdentifier=%p [Install] -WantedBy={{service}}.target +WantedBy={{ mastodon_service }}.target diff --git a/webapps/mastodon/templates/mastodon-streaming.service.j2 b/webapps/mastodon/templates/mastodon-streaming.service.j2 index 859d7506..bf5bbb36 100644 --- a/webapps/mastodon/templates/mastodon-streaming.service.j2 +++ b/webapps/mastodon/templates/mastodon-streaming.service.j2 @@ -1,16 +1,16 @@ [Unit] Description=mastodon-streaming After=network.target -PartOf={{service}}.target +PartOf={{ mastodon_service }}.target [Service] Type=simple -User={{service}} -Group={{service}} +User={{ mastodon_service }} +Group={{ mastodon_service }} UMask=0027 -WorkingDirectory=/home/{{service}}/mastodon/ +WorkingDirectory=/home/{{ mastodon_service }}/mastodon/ Environment="NODE_ENV=production" -Environment="PORT={{ node_port | default('4000')}}" +Environment="PORT={{ mastodon_node_port | default('4000') }}" Environment="STREAMING_CLUSTER_NUM=1" ExecStart=/bin/bash -lc "node ./streaming" TimeoutSec=15 @@ -18,4 +18,4 @@ Restart=always SyslogIdentifier=%p [Install] -WantedBy={{service}}.target +WantedBy={{ mastodon_service }}.target diff --git a/webapps/mastodon/templates/mastodon-web.service.j2 b/webapps/mastodon/templates/mastodon-web.service.j2 index 5f249325..ba936851 100644 --- a/webapps/mastodon/templates/mastodon-web.service.j2 +++ b/webapps/mastodon/templates/mastodon-web.service.j2 @@ -1,23 +1,23 @@ [Unit] Description=mastodon-web After=network.target -PartOf={{service}}.target +PartOf={{ mastodon_service }}.target [Service] Type=simple -User={{service}} -Group={{service}} +User={{ mastodon_service }} +Group={{ mastodon_service }} UMask=0027 -WorkingDirectory=/home/{{service}}/mastodon/ +WorkingDirectory=/home/{{ mastodon_service }}/mastodon/ Environment="RAILS_ENV=production" -Environment="PORT={{puma_port|default('3000')}}" +Environment="PORT={{ mastodon_puma_port | default('3000') }}" Environment="RAILS_LOG_LEVEL=warn" Environment="LD_PRELOAD=libjemalloc.so" -ExecStart=/home/{{service}}/.rbenv/shims/bundle exec puma -C config/puma.rb +ExecStart=/home/{{ mastodon_service }}/.rbenv/shims/bundle exec puma -C config/puma.rb ExecReload=/bin/kill -SIGUSR1 $MAINPID TimeoutSec=15 Restart=always SyslogIdentifier=%p [Install] -WantedBy={{service}}.target +WantedBy={{ mastodon_service }}.target diff --git a/webapps/mastodon/templates/mastodon.target.j2 b/webapps/mastodon/templates/mastodon.target.j2 index 0eb5475a..858c3b4d 100644 --- a/webapps/mastodon/templates/mastodon.target.j2 +++ b/webapps/mastodon/templates/mastodon.target.j2 @@ -2,7 +2,7 @@ Description=Mastodon Microblogging service Wants=redis-server.service After=redis-server.service -Requires={{ service }}-web.service {{ service }}-sidekiq.service {{ service }}-streaming.service +Requires={{ mastodon_service }}-web.service {{ mastodon_service }}-sidekiq.service {{ mastodon_service }}-streaming.service [Install] WantedBy=multi-user.target diff --git a/webapps/mastodon/templates/vhost.j2 b/webapps/mastodon/templates/vhost.j2 index 673cb186..6639f5b7 100644 --- a/webapps/mastodon/templates/vhost.j2 +++ b/webapps/mastodon/templates/vhost.j2 @@ -6,7 +6,7 @@ map $http_upgrade $connection_upgrade { server { listen 80; listen [::]:80; - server_name {{ domains |first }}; + server_name {{ mastodon_domains |first }}; include /etc/nginx/snippets/letsencrypt.conf; {% if ssl.stat.exists %} location / { return 301 https://$host$request_uri; } @@ -17,12 +17,12 @@ server { server { listen 443 ssl http2; listen [::]:443 ssl http2; - server_name {{ domains |first }}; + server_name {{ mastodon_domains |first }}; include /etc/nginx/snippets/letsencrypt.conf; - ssl_certificate /etc/letsencrypt/live/{{ domains |first }}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{{ domains |first }}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{{ domains |first }}/chain.pem; + ssl_certificate /etc/letsencrypt/live/{{ mastodon_domains |first }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ mastodon_domains |first }}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{{ mastodon_domains |first }}/chain.pem; # OCSP stapling ssl_stapling on; @@ -33,7 +33,7 @@ server { sendfile on; client_max_body_size 0; - root /home/{{ service }}/mastodon/public; + root /home/{{ mastodon_service }}/mastodon/public; gzip on; gzip_disable "msie6"; @@ -45,7 +45,7 @@ server { gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; #add_header Strict-Transport-Security "max-age=31536000"; - #add_header Content-Security-Policy "style-src 'self' 'unsafe-inline'; script-src 'self'; object-src 'self'; img-src data: https:; media-src data: https:; connect-src 'self' wss://{{ domains |first }}; upgrade-insecure-requests"; + #add_header Content-Security-Policy "style-src 'self' 'unsafe-inline'; script-src 'self'; object-src 'self'; img-src data: https:; media-src data: https:; connect-src 'self' wss://{{ mastodon_domains |first }}; upgrade-insecure-requests"; location / { try_files $uri @proxy; @@ -64,7 +64,7 @@ server { proxy_set_header Proxy ""; proxy_pass_header Server; - proxy_pass http://127.0.0.1:{{puma_port|default('3000')}}; + proxy_pass http://127.0.0.1:{{ mastodon_puma_port | default('3000') }}; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; @@ -81,7 +81,7 @@ server { proxy_set_header X-Forwarded-Proto https; proxy_set_header Proxy ""; - proxy_pass http://127.0.0.1:{{ node_port | default('4000')}}; + proxy_pass http://127.0.0.1:{{ mastodon_node_port | default('4000') }}; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; From f29fa00eff2a36187653730fe01b21c7796130f2 Mon Sep 17 00:00:00 2001 From: Mathieu Gauthier-Pilote Date: Fri, 24 May 2024 09:50:41 -0400 Subject: [PATCH 9/9] ansible.builtin. prefix for modules --- webapps/mastodon/tasks/main.yml | 78 +++++++++++++++--------------- webapps/mastodon/tasks/upgrade.yml | 54 ++++++++++----------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/webapps/mastodon/tasks/main.yml b/webapps/mastodon/tasks/main.yml index d08f306f..1f1cf6a3 100644 --- a/webapps/mastodon/tasks/main.yml +++ b/webapps/mastodon/tasks/main.yml @@ -2,17 +2,17 @@ # tasks file for mastodon install - name: Install main system dependencies - apt: + ansible.builtin.apt: name: "{{ mastodon_system_dep }}" update_cache: yes - name: Install npm on Debian 12 - apt: + ansible.builtin.apt: name: npm when: ansible_distribution_major_version is version('12', '>=') - name: Install corepack via npm on Debian 12 - shell: npm install -g corepack + ansible.builtin.shell: npm install -g corepack when: ansible_distribution_major_version is version('12', '>=') - name: Fix permissions for corepack @@ -24,17 +24,17 @@ when: ansible_distribution_major_version is version('12', '>=') - name: Enable yarn (via corepack) - shell: "corepack enable; yarn set version classic" + ansible.builtin.shell: "corepack enable; yarn set version classic" - name: Add PostgreSQL user - postgresql_user: + community.postgresql.postgresql_user: name: "{{ mastodon_db_user }}" password: "{{ mastodon_db_password }}" role_attr_flags: CREATEDB become_user: postgres - name: Add UNIX account - user: + ansible.builtin.user: name: "{{ mastodon_service }}" shell: /bin/bash # umask: "0022" nécessite ansible-core 2.12 @@ -47,7 +47,7 @@ - rbenv_ruby_version: "{{ mastodon_ruby_version }}" - name: Clone Mastodon repo (git) - git: + ansible.builtin.git: repo: "{{ mastodon_git_url }}" dest: "~/mastodon/" version: "{{ mastodon_git_version | default(omit) }}" @@ -58,24 +58,24 @@ - block: - name: Install bundler - shell: ". ~/.profile && gem install bundler --no-document" + ansible.builtin.shell: ". ~/.profile && gem install bundler --no-document" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Install gem dependencies - shell: ". ~/.profile && bundle install --deployment --without development test -j{{ ansible_processor_count }}" + ansible.builtin.shell: ". ~/.profile && bundle install --deployment --without development test -j{{ ansible_processor_count }}" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Install javascript dependencies - shell: ". ~/.profile && yarn install --pure-lockfile" + ansible.builtin.shell: ". ~/.profile && yarn install --pure-lockfile" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh become_user: "{{ mastodon_service }}" - name: Template .env.production configuration file - template: + ansible.builtin.template: src: "env.j2" dest: "~{{ mastodon_service }}/mastodon/.env.production" owner: "{{ mastodon_service }}" @@ -83,7 +83,7 @@ mode: "0640" - name: Check if secrets need to be generated or not - shell: "grep -P SECRET_KEY_BASE=[[:alnum:]]{128} .env.production" + ansible.builtin.shell: "grep -P SECRET_KEY_BASE=[[:alnum:]]{128} .env.production" args: chdir: "~/mastodon" become_user: "{{ mastodon_service }}" @@ -92,41 +92,41 @@ - block: - name: Generate secret for SECRET_KEY_BASE - shell: '. ~/.profile && sed -i -r "s/SECRET_KEY_BASE=/SECRET_KEY_BASE=$(RAILS_ENV=production bundle exec rake secret)/" .env.production' + ansible.builtin.shell: '. ~/.profile && sed -i -r "s/SECRET_KEY_BASE=/SECRET_KEY_BASE=$(RAILS_ENV=production bundle exec rake secret)/" .env.production' args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Generate secret for OTP_SECRET - shell: '. ~/.profile && sed -i -r "s/OTP_SECRET=/OTP_SECRET=$(RAILS_ENV=production bundle exec rake secret)/" .env.production' + ansible.builtin.shell: '. ~/.profile && sed -i -r "s/OTP_SECRET=/OTP_SECRET=$(RAILS_ENV=production bundle exec rake secret)/" .env.production' args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Generate secret for VAPID_PRIVATE_KEY and VAPID_PUBLIC_KEY - shell: . ~/.profile && RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key > vapid.tmp | head -1 | cut -c 19- + ansible.builtin.shell: . ~/.profile && RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key > vapid.tmp | head -1 | cut -c 19- args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Read VAPID_PRIVATE_KEY secret from temp file - shell: "cat vapid.tmp | head -1 | cut -c 19-" + ansible.builtin.shell: "cat vapid.tmp | head -1 | cut -c 19-" args: chdir: "~/mastodon" register: app_vapid_private_key - name: Read VAPID_PUBLIC_KEY secret from temp file - shell: "cat vapid.tmp | tail -1 | cut -c 18-" + ansible.builtin.shell: "cat vapid.tmp | tail -1 | cut -c 18-" args: chdir: "~/mastodon" register: app_vapid_public_key - name: Delete secrets temp file - file: + ansible.builtin.file: path: "~/mastodon/vapid.tmp" state: absent - name: Write app_vapid_private_key to production .env file - lineinfile: + ansible.builtin.lineinfile: path: "~/mastodon/.env.production" regexp: '^VAPID_PRIVATE_KEY=' line: "VAPID_PRIVATE_KEY={{ mastodon_app_vapid_private_key.stdout }}" - name: Write app_vapid_public_key to production .env file - lineinfile: + ansible.builtin.lineinfile: path: "~/mastodon/.env.production" regexp: '^VAPID_PUBLIC_KEY=' line: "VAPID_PUBLIC_KEY={{ mastodon_app_vapid_public_key.stdout }}" @@ -134,14 +134,14 @@ when: "secrets.rc == 1" - name: Check if mastodon database is already present or not - shell: | + ansible.builtin.shell: | psql -lqt | cut -d \| -f 1 | grep -qw {{ mastodon_service }}_production become_user: postgres register: db_present failed_when: "db_present.rc == 2" - name: Setup database schema if database not already present - shell: ". ~/.profile && RAILS_ENV=production SAFETY_ASSURED=1 bundle exec rails db:setup" + ansible.builtin.shell: ". ~/.profile && RAILS_ENV=production SAFETY_ASSURED=1 bundle exec rails db:setup" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh @@ -149,14 +149,14 @@ when: "db_present.rc == 1" - name: Precompile assets - shell: ". ~/.profile && RAILS_ENV=production bundle exec rails assets:precompile" + ansible.builtin.shell: ". ~/.profile && RAILS_ENV=production bundle exec rails assets:precompile" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh become_user: "{{ mastodon_service }}" - name: Adjust permissions of files in public folder - file: + ansible.builtin.file: path: "~/mastodon/public" state: directory mode: 'o=rX' @@ -164,27 +164,27 @@ become_user: "{{ mastodon_service }}" - name: Add systemd target - template: + ansible.builtin.template: src: "mastodon.target.j2" dest: "/etc/systemd/system/{{ mastodon_service }}.target" - name: Add systemd web unit - template: + ansible.builtin.template: src: "mastodon-web.service.j2" dest: "/etc/systemd/system/{{ mastodon_service }}-web.service" - name: Add systemd sidekiq unit - template: + ansible.builtin.template: src: "mastodon-sidekiq.service.j2" dest: "/etc/systemd/system/{{ mastodon_service }}-sidekiq.service" - name: Add systemd streaming unit - template: + ansible.builtin.template: src: "mastodon-streaming.service.j2" dest: "/etc/systemd/system/{{ mastodon_service }}-streaming.service" - name: Enable systemd units - systemd: + ansible.builtin.systemd: name: "{{ item }}" enabled: yes daemon_reload: yes @@ -195,51 +195,51 @@ - "{{ mastodon_service }}-streaming.service" - name: Start services - service: + ansible.builtin.service: name: "{{ mastodon_service }}.target" state: started - name: Check if SSL certificate is present and register result - stat: + ansible.builtin.stat: path: "/etc/letsencrypt/live/{{ mastodon_domains |first }}/fullchain.pem" register: ssl - name: Generate certificate only if required (first time) block: - name: Template vhost without SSL for successfull LE challengce - template: + ansible.builtin.template: src: "vhost.j2" dest: "/etc/nginx/sites-available/{{ mastodon_service }}" - name: Enable temporary nginx vhost for LE - file: + ansible.builtin.file: src: "/etc/nginx/sites-available/{{ mastodon_service }}" dest: "/etc/nginx/sites-enabled/{{ mastodon_service }}" state: link - name: Reload nginx conf - service: + ansible.builtin.service: name: nginx state: reloaded - name: Generate certificate with certbot - shell: certbot certonly --webroot --webroot-path /var/lib/letsencrypt -d {{ mastodon_domains |first }} + ansible.builtin.shell: certbot certonly --webroot --webroot-path /var/lib/letsencrypt -d {{ mastodon_domains |first }} when: ssl.stat.exists == false - name: (Re)check if SSL certificate is present and register result - stat: + ansible.builtin.stat: path: "/etc/letsencrypt/live/{{ mastodon_domains |first }}/fullchain.pem" register: ssl - name: (Re)template conf file for nginx vhost with SSL - template: + ansible.builtin.template: src: "vhost.j2" dest: "/etc/nginx/sites-available/{{ mastodon_service }}" - name: Enable nginx vhost for mastodon - file: + ansible.builtin.file: src: "/etc/nginx/sites-available/{{ mastodon_service }}" dest: "/etc/nginx/sites-enabled/{{ mastodon_service }}" state: link - name: Reload nginx conf - service: + ansible.builtin.service: name: nginx state: reloaded diff --git a/webapps/mastodon/tasks/upgrade.yml b/webapps/mastodon/tasks/upgrade.yml index d1b8c57a..97e4f42b 100644 --- a/webapps/mastodon/tasks/upgrade.yml +++ b/webapps/mastodon/tasks/upgrade.yml @@ -2,97 +2,97 @@ # tasks file for mastodon upgrade - name: Dump database to a file with compression - postgresql_db: - name: "{{ service }}_production" + community.postgresql.postgresql_db: + name: "{{ mastodon_service }}_production" state: dump - target: "~/{{ service }}_production.sql.gz" + target: "~/{{ mastodon_service }}_production.sql.gz" become_user: postgres - name: Install Ruby for service user (rbenv) include_role: name: rbenv vars: - - username: "{{ service }}" - - rbenv_ruby_version: "{{ ruby_version }}" + - username: "{{ mastodon_service }}" + - rbenv_ruby_version: "{{ mastodon_ruby_version }}" - name: Checkout (git) - git: - repo: "{{ git_url }}" + ansible.builtin.git: + repo: "{{ mastodon_git_url }}" dest: "~/mastodon/" - version: "{{ git_version | default(omit) }}" + version: "{{ mastodon_git_version | default(omit) }}" force: yes update: yes - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" - block: - name: Install bundler - shell: ". ~/.profile && gem install bundler --no-document" + ansible.builtin.shell: ". ~/.profile && gem install bundler --no-document" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Install gem dependencies - shell: ". ~/.profile && bundle install --deployment --without development test -j{{ ansible_processor_count }}" + ansible.builtin.shell: ". ~/.profile && bundle install --deployment --without development test -j{{ ansible_processor_count }}" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Install javascript dependencies - shell: ". ~/.profile && yarn install --pure-lockfile" + ansible.builtin.shell: ". ~/.profile && yarn install --pure-lockfile" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Upgrade browsers list db - shell: ". ~/.profile && npx update-browserslist-db@latest" + ansible.builtin.shell: ". ~/.profile && npx update-browserslist-db@latest" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Run database migrations, skipping post-deployment - shell: ". ~/.profile && SKIP_POST_DEPLOYMENT_MIGRATIONS=true RAILS_ENV=production bundle exec rails db:migrate" + ansible.builtin.shell: ". ~/.profile && SKIP_POST_DEPLOYMENT_MIGRATIONS=true RAILS_ENV=production bundle exec rails db:migrate" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Precompile assets - shell: ". ~/.profile && RAILS_ENV=production bundle exec rails assets:precompile" + ansible.builtin.shell: ". ~/.profile && RAILS_ENV=production bundle exec rails assets:precompile" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - name: Adjust permissions of files in public folder - file: + ansible.builtin.file: path: "~/mastodon/public" state: directory mode: 'o=rX' recurse: true - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" - name: Restart services - service: - name: "{{ service }}.target" + ansible.builtin.service: + name: "{{ mastodon_service }}.target" state: restarted - name: Run database migrations, this time including post-deployment - shell: ". ~/.profile && RAILS_ENV=production bundle exec rails db:migrate" + ansible.builtin.shell: ". ~/.profile && RAILS_ENV=production bundle exec rails db:migrate" args: chdir: "~/mastodon" executable: /bin/bash # fails with /bin/sh - become_user: "{{ service }}" + become_user: "{{ mastodon_service }}" - name: Restart services - service: - name: "{{ service }}.target" + ansible.builtin.service: + name: "{{ mastodon_service }}.target" state: restarted - name: Define variable to skip next task by default - set_fact: + ansible.builtin.set_fact: keep_db_dump: true - name: Remove database dump - file: - path: "~/{{ service }}_production.sql.gz" + ansible.builtin.file: + path: "~/{{ mastodon_service }}_production.sql.gz" state: absent become_user: postgres when: keep_db_dump is undefined tags: clean - name: Reload nginx conf - service: + ansible.builtin.service: name: nginx state: reloaded