role mastodon added

This commit is contained in:
rene
2022-03-15 14:23:01 +01:00
parent ba812a9cdc
commit 8b4579bb90
21 changed files with 584 additions and 2 deletions

View File

@@ -0,0 +1,17 @@
---
# Load distro specific variables
- include_vars: "{{ ansible_distribution }}.yml"
tags: always
- include_vars: "{{ ansible_fqdn }}.yml"
ignore_errors: True
- include_tasks: system_setup/prepare_packagemanager.yml
- include_role: name=database
- include_tasks: system_setup/prepare_database.yml
- include_role: name=webserver
- include_tasks: system_setup/nginx.yml
- include_tasks: system_setup/user.yml
- include_tasks: system_setup/ruby.yml
- include_tasks: system_setup/mastodon.yml
- include_tasks: system_setup/letsencrypt.yml

View File

@@ -0,0 +1,31 @@
---
- stat: path=/etc/letsencrypt/live/{{ mastodon_host }}/fullchain.pem
register: letsencrypt_cert
- name: Copy letsencrypt nginx config
template:
src: ../files/nginx/letsencrypt.conf.j2
dest: /etc/nginx/sites-available/mastodon.conf
when: not letsencrypt_cert.stat.exists
- name: Symlink enabled site
file:
src: "/etc/nginx/sites-available/mastodon.conf"
dest: "/etc/nginx/sites-enabled/mastodon.conf"
state: link
when: not letsencrypt_cert.stat.exists
- name: Reload nginx
command: "systemctl reload nginx"
- name: Install letsencrypt cert
command: letsencrypt certonly -n --webroot -d {{ mastodon_host }} -w {{ mastodon_home }}/{{ mastodon_path }}/public/ --email "webmaster@{{ mastodon_host }}" --agree-tos && systemctl reload nginx
when: not letsencrypt_cert.stat.exists
- name: Letsencrypt Job
cron:
name: "letsencrypt renew"
minute: "15"
hour: "0"
job: "letsencrypt renew && service nginx reload"

View File

@@ -0,0 +1,100 @@
- name: Clone mastodon
git:
repo: "https://github.com/mastodon/mastodon.git"
dest: "{{ mastodon_home }}/{{mastodon_path}}"
clone: true
# - name: Update to latest version
# shell: "git fetch; git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)"
# args:
# chdir: "{{ mastodon_home }}/{{ mastodon_path }}"
- name: Bundle install
shell: |
~/.rbenv/shims/bundle config set --local deployment 'true' && \
~/.rbenv/shims/bundle config set --local without 'test' && \
~/.rbenv/shims/bundle config set --local with 'development' && \
~/.rbenv/shims/bundle install -j$(getconf _NPROCESSORS_ONLN)
args:
chdir: "{{ mastodon_home }}/{{ mastodon_path }}"
- name: Yarn install
command: yarn install --pure-lockfile
args:
chdir: "{{ mastodon_home }}/{{ mastodon_path }}"
- name: Install systemd sidekiq Service Files
template:
src: mastodon-sidekiq.service.j2
dest: /etc/systemd/system/mastodon-sidekiq.service
become: true
become_user: root
- name: Install systemd web Service Files
template:
src: mastodon-web.service.j2
dest: /etc/systemd/system/mastodon-web.service
become: true
become_user: root
- name: Install systemd streaming Service Files
template:
src: mastodon-streaming.service.j2
dest: /etc/systemd/system/mastodon-streaming.service
become: true
become_user: root
- name: Media cleanup cronjob
cron:
name: "media cleanup"
minute: "15"
hour: "1"
job: '/bin/bash -c ''export PATH="$HOME/.rbenv/bin:$PATH"; eval "$(rbenv init -)"; cd {{ mastodon_home }}/{{ mastodon_path }} && RAILS_ENV=production ./bin/tootctl media remove'''
- stat: path={{ mastodon_home }}/{{ mastodon_path }}/.env.production
register: production_config
- name: Migrate database
shell: "RAILS_ENV=production ~/.rbenv/shims/bundle exec rails db:migrate"
args:
chdir: "{{ mastodon_home }}/{{ mastodon_path }}"
when: production_config.stat.exists
- name: Precompile assets
shell: "RAILS_ENV=production ~/.rbenv/shims/bundle exec rails assets:precompile"
args:
chdir: "{{ mastodon_home }}/{{ mastodon_path }}"
when: production_config.stat.exists
- name: Enable mastodon-web
command: systemctl enable mastodon-web.service
become: true
become_user: root
- name: Enable mastodon-streaming
command: systemctl enable mastodon-streaming.service
become: true
become_user: root
- name: Enable mastodon-sidekiq
command: systemctl enable mastodon-sidekiq.service
become: true
become_user: root
- name: Restart mastodon-web
command: systemctl restart mastodon-web.service
when: production_config.stat.exists
become: true
become_user: root
- name: Restart mastodon-streaming
command: systemctl restart mastodon-streaming.service
when: production_config.stat.exists
become: true
become_user: root
- name: Restart mastodon-sidekiq
command: systemctl restart mastodon-sidekiq.service
when: production_config.stat.exists
become: true
become_user: root

View File

@@ -0,0 +1,18 @@
---
- name: mastodon | Copy nginx config
template:
src: ../files/nginx/mastodon.conf.j2
dest: /etc/nginx/sites-available/mastodon.conf
when:
- mastodon_host is defined
notify: restart_nginx
- name: mastodon | Symlink enabled site
file:
src: "/etc/nginx/sites-available/mastodon.conf"
dest: "/etc/nginx/sites-enabled/mastodon.conf"
state: link
when:
- mastodon_host is defined
notify: restart_nginx

View File

@@ -0,0 +1,16 @@
---
- name: mastodon | Install packages
package:
name: "{{ item.package }}"
update_cache: yes
cache_valid_time: 3600
state: latest
install_recommends: no
with_items: "{{ packages }}"
- name: mastodon | nodejs alternative
alternatives:
name: node
link: /usr/bin/node
path: /usr/bin/nodejs

View File

@@ -0,0 +1,47 @@
- name: mastodon | postgres | Create database {{ mastodon_db }}
postgresql_db:
name: mastodon | postgres | "{{ mastodon_db }}"
login_host: "{{ mastodon_db_login_host }}"
login_password: "{{ mastodon_db_login_password }}"
login_user: "{{ mastodon_db_login_user }}"
port: "{{ mastodon_db_port }}"
register: create_remote_db
when:
- mastodon_db_login_user is defined
- mastodon_db_login_host is defined
- mastodon_db_login_password is defined
- mastodon_db_port is defined
- name: mastodon | postgres | Create database user {{ mastodon_db_user }}
postgresql_user:
db: "{{ mastodon_db }}"
name: mastodon | postgres | "{{ mastodon_db_user }}"
password: "{{ mastodon_db_password }}"
login_host: "{{ mastodon_db_login_host }}"
login_password: "{{ mastodon_db_login_password }}"
login_user: "{{ mastodon_db_login_user }}"
port: "{{ mastodon_db_port }}"
role_attr_flags: CREATEDB
register: create_remote_db_user
when:
- mastodon_db_login_user is defined
- mastodon_db_login_host is defined
- mastodon_db_login_password is defined
- mastodon_db_port is defined
- name: mastodon | postgres | Create database {{ mastodon_db }}
postgresql_db:
name: mastodon | postgres | "{{ mastodon_db }}"
login_unix_socket: "{{ mastodon_db_login_unix_socket }}"
register: create_local_db
when: create_remote_db is skipped
- name: mastodon | postgres | Create database user {{ mastodon_db_user }}
postgresql_user:
db: "{{ mastodon_db }}"
name: mastodon | postgres | "{{ mastodon_db_user }}"
password: "{{ mastodon_db_password }}"
encrypted: yes
login_unix_socket: "{{ mastodon_db_login_unix_socket }}"
role_attr_flags: CREATEDB
when: create_remote_db_user is skipped

View File

@@ -0,0 +1,22 @@
- name: mastodon | package manager | get nodejs prepare script
- name: mastodon | package manager | add gpg keys
apt_key:
id: "{{ item.id }}"
url: "{{ item.url }}"
state: present
loop:
- { id: "72ECF46A56B4AD39C907BBB71646B01B86E50310", url: "https://dl.yarnpkg.com/debian/pubkey.gpg" }
- { id: "9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280", url: "https://deb.nodesource.com/gpgkey/nodesource.gpg.key" }
- name: mastodon | package manager | add repos
apt_repository:
repo: "{{ item.repo }}"
state: present
mode: 0644 # not required. The octal mode for newly created files in sources.list.d
update_cache: no
validate_certs: yes # not required. If C(no), SSL certificates for the target repo will not be validated. This should only be used on personally controlled sites using self-signed certificates.
filename: "{{ item.filename }}"
loop:
- { repo: "deb https://dl.yarnpkg.com/debian/ stable main", filename: "yarn"}
- { repo: "deb https://deb.nodesource.com/node_{{ node_major_version }}.x {{ ansible_lsb.codename }} main", filename: "nodejs"}

View File

@@ -0,0 +1,57 @@
---
- name: mastodon | Clone rbenv
git:
repo: "https://github.com/rbenv/rbenv.git"
dest: "~/.rbenv"
clone: true
version: "{{ rbenv_version }}"
- name: mastodon | Clone ruby-build
git:
repo: "https://github.com/rbenv/ruby-build.git"
dest: "~/.rbenv/plugins/ruby-build"
clone: true
version: "{{ ruby_build_version }}"
register: ruby_build
- name: mastodon | Configure rbenv
command: ./configure
args:
chdir: "~/.rbenv/src"
register: rbenv_configure
- name: mastodon | Build rbenv
command: make
args:
chdir: "~/.rbenv/src"
when: rbenv_configure is succeeded
- name: mastodon | Update profile settings
copy:
dest: "~/.bashrc"
content: |
export PATH="~/.rbenv/bin:${PATH}"
eval "$(rbenv init -)"
- name: mastodon | Check if the Ruby version is already installed
shell: "~/.rbenv/bin/rbenv versions | grep -q {{ ruby_version }}"
register: ruby_installed
ignore_errors: yes
check_mode: no
- name: mastodon | Install Ruby {{ ruby_version }}
shell: "~/.rbenv/bin/rbenv install {{ ruby_version }}"
args:
executable: /bin/bash
when: ruby_installed is failed
- name: mastodon | Set the default Ruby version to {{ ruby_version }}
shell: "~/.rbenv/bin/rbenv global {{ ruby_version }}"
args:
executable: /bin/bash
register: default_ruby_version
- name: mastodon | Install bundler
shell: 'export PATH="$HOME/.rbenv/bin:$PATH"; eval "$(rbenv init -)"; gem install bundler:{{ bundler_version }}'
args:
executable: /bin/bash
when: default_ruby_version is succeeded

View File

@@ -0,0 +1,6 @@
- name: mastodon | create mastodon user
user:
name: "{{ mastodon_user }}"
createhome: true
shell: /bin/bash
home: "{{ mastodon_home }}"

View File

@@ -0,0 +1,8 @@
# This starts a simple nginx for the letsencrypt acme challenge
server {
listen 80;
listen [::]:80;
server_name {{ mastodon_host }};
root {{ mastodon_home }}/{{ mastodon_path }}/public;
location /.well-known/acme-challenge/ { allow all; }
}

View File

@@ -0,0 +1,16 @@
[Unit]
Description=mastodon-sidekiq
After=network.target
[Service]
Type=simple
User=mastodon
WorkingDirectory={{ mastodon_home }}/{{ mastodon_path }}
Environment="RAILS_ENV=production"
Environment="DB_POOL=5"
ExecStart={{ mastodon_home }}/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q push -q mailers -q pull
TimeoutSec=15
Restart=always
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,16 @@
[Unit]
Description=mastodon-streaming
After=network.target
[Service]
Type=simple
User=mastodon
WorkingDirectory={{ mastodon_home }}/{{ mastodon_path }}
Environment="NODE_ENV=production"
Environment="PORT=4000"
ExecStart=/usr/bin/npm run start
TimeoutSec=15
Restart=always
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,17 @@
[Unit]
Description=mastodon-web
After=network.target
[Service]
Type=simple
User=mastodon
WorkingDirectory={{ mastodon_home }}/{{ mastodon_path }}
Environment="RAILS_ENV=production"
Environment="PORT=3000"
ExecStart={{ mastodon_home }}/.rbenv/shims/bundle exec puma -C config/puma.rb
ExecReload=/bin/kill -SIGUSR1 $MAINPID
TimeoutSec=15
Restart=always
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,100 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name {{ mastodon_host }};
# Useful for Let's Encrypt
location /.well-known/acme-challenge/ { allow all; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ mastodon_host }};
ssl_protocols TLSv1.2;
ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
{% if disable_letsencrypt != "true" %}
ssl_certificate /etc/letsencrypt/live/{{ mastodon_host }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ mastodon_host }}/privkey.pem;
{% endif %}
keepalive_timeout 70;
sendfile on;
client_max_body_size 8m;
root {{ mastodon_home }}/{{ mastodon_path }}/public;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
{% if disable_hsts == "true" %}
add_header Strict-Transport-Security "max-age=31536000";
{% endif %}
location / {
try_files $uri @proxy;
}
location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri @proxy;
}
location /sw.js {
add_header Cache-Control "public, max-age=0";
try_files $uri @proxy;
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://127.0.0.1:3000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
location /api/v1/streaming {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Proxy "";
proxy_pass http://127.0.0.1:4000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
tcp_nodelay on;
}
error_page 500 501 502 503 504 /500.html;
}

View File

@@ -0,0 +1,33 @@
mastodon_db_login_unix_socket: '/var/run/postgresql'
packages:
- package: "autoconf"
- package: "bison"
- package: "build-essential"
- package: "curl"
- package: "cron"
- package: "ffmpeg"
- package: "file"
- package: "g++"
- package: "gcc"
- package: "git"
- package: "imagemagick"
- package: "libffi-dev"
- package: "libgdbm-dev"
- package: "libicu-dev"
- package: "libidn11-dev"
- package: "libncurses5-dev"
- package: "libpq-dev"
- package: "libprotobuf-dev"
- package: "libreadline-dev"
- package: "libssl-dev"
- package: "libxml2-dev"
- package: "libxslt1-dev"
- package: "libyaml-dev"
- package: "nodejs"
- package: "pkg-config"
- package: "protobuf-compiler"
- package: "sudo"
- package: "systemd"
- package: "yarn"
- package: "zlib1g-dev"

View File

@@ -0,0 +1,20 @@
webserver: True
nginx: True
database: True
postgres: True
redis: True
ruby_version: "2.7.4"
rbenv_version: "v1.1.2"
ruby_build_version: "v20210707"
bundler_version: "2.1.4"
node_major_version: "12"
os_family: "{{ ansible_os_family|lower }}"
mastodon_user: "mastodon"
mastodon_home: "/home/{{ mastodon_user }}"
mastodon_db_user: "{{ mastodon_user }}"
mastodon_path: "live"
mastodon_db: "{{ mastodon_user }}_development"
mastodon_db_port: 5432
disable_hsts: "false"
disable_letsencrypt: "false"