Deploy mastodon v0.1

This commit is contained in:
2026-02-03 10:52:11 +02:00
commit 43395ee775
34 changed files with 794 additions and 0 deletions

38
roles/mastodon/README.md Normal file
View File

@@ -0,0 +1,38 @@
Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).

View File

@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# defaults file for mastodon

View File

@@ -0,0 +1,3 @@
#SPDX-License-Identifier: MIT-0
---
# handlers file for mastodon

View File

@@ -0,0 +1,35 @@
---
# SPDX-License-Identifier: MIT-0
galaxy_info:
author: Simonas K.
description: mastodon deployment
company: wtf.lt
# 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: MIT
min_ansible_version: 2.1
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
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.

View File

@@ -0,0 +1,30 @@
---
- name: Populate database variables
ansible.builtin.include_vars:
file: db.yml
- name: Create DB instance for mastodon
containers.podman.podman_container:
name: database
image: docker.io/library/postgres:17
network:
- "{{ mastodon_networks['mastodon_internal']['name'] }}"
env:
POSTGRES_DB: mastodon
POSTGRES_USER: "{{ mastodon_database.username }}"
POSTGRES_PASSWORD: "{{ mastodon_database.password }}"
volumes:
- "/home/apps/mastodon/postgresql:/var/lib/postgresql/data:Z"
generate_systemd:
new: true
restart_policy: "always"
path: "~/.config/systemd/user/"
force: true
healthcheck: "pg_isready -U postgres"
- name: Activate database container service
ansible.builtin.systemd_service:
name: container-database.service
state: started
enabled: true
scope: user

View File

@@ -0,0 +1,31 @@
---
- name: Create Elasticsearch instance for mastodon
containers.podman.podman_container:
name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.29
network:
- "{{ mastodon_networks['mastodon_internal']['name'] }}"
- "{{ mastodon_networks['mastodon_external']['name'] }}"
volumes:
- "/home/apps/mastodon/elasticsearch:/usr/share/elasticsearch/data:Z"
env:
ES_JAVA_OPTS: "-Xms512m -Xmx512m -Des.enforce.bootstrap.checks=true"
xpack.license.self_generated.type: "basic"
xpack.security.enabled: "false"
xpack.watcher.enabled: "false"
xpack.graph.enabled: "false"
xpack.ml.enabled: "false"
bootstrap.memory_lock: "true"
cluster.name: "es-mastodon"
discovery.type: "single-node"
thread_pool.write.queue_size: "1000"
# generate_systemd:
# new: true
# restart_policy: "always"
# path: "~/.config/systemd/user/"
# force: true
restart_policy: "always"
healthcheck: "curl --silent --fail localhost:9200/_cluster/health || exit 1"
ulimit:
- "nofile=65536:65536"
- "memlock=-1:-1"

View File

@@ -0,0 +1,39 @@
#SPDX-License-Identifier: MIT-0
---
# tasks file for mastodon
- name: Setup mastodon networks
containers.podman.podman_network:
name: "{{ item['key'] }}"
driver: "{{ item['value']['driver'] }}"
disable_dns: "{{ item['value']['disable_dns'] }}"
loop: "{{ mastodon_networks | dict2items }}"
- name: Setup local directories
ansible.builtin.file:
name: "{{ item }}"
state: directory
loop: "{{ mastodon_local_dirs }}"
- name: Populate active record variables
ansible.builtin.include_vars:
file: web.yml
- name: Populate smtp variables
ansible.builtin.include_vars:
file: smtp.yml
- name: Create database container instance
ansible.builtin.include_tasks: db.yml
- name: Create redis container instance
ansible.builtin.include_tasks: redis.yml
- name: Create elasticsearch container instance
ansible.builtin.include_tasks: elasticsearch.yml
- name: Create web container instance
ansible.builtin.include_tasks: web.yml
- name: Create sidekiq container instance
ansible.builtin.include_tasks: sidekiq.yml

View File

@@ -0,0 +1,22 @@
---
- name: Create Redis instance for mastodon
containers.podman.podman_container:
name: redis
image: docker.io/library/redis:7
network:
- "{{ mastodon_networks['mastodon_internal']['name'] }}"
volumes:
- "/home/apps/mastodon/redis:/data:Z"
generate_systemd:
new: true
restart_policy: "always"
path: "~/.config/systemd/user/"
force: true
healthcheck: "redis-cli ping"
- name: Activate elasticsearch container service
ansible.builtin.systemd_service:
name: container-redis.service
state: started
enabled: true
scope: user

View File

@@ -0,0 +1,48 @@
---
# TODO: it's not idempotent
- name: Create Sidekiq instance of mastodon
containers.podman.podman_container:
name: sidekiq
image: ghcr.io/mastodon/mastodon:v4.5.5
network:
- "{{ mastodon_networks['mastodon_internal']['name'] }}"
- "{{ mastodon_networks['mastodon_external']['name'] }}"
command: "bundle exec sidekiq"
env:
LOCAL_DOMAIN: "wtf.lt"
REDIS_HOST: redis
REDIS_PORT: 6379
DB_HOST: database
DB_NAME: mastodon
DB_USER: "{{ mastodon_database.username }}"
DB_PASS: "{{ mastodon_database.password }}"
DB_PORT: 5432
ES_ENABLED: true
ES_HOST: elasticsearch
ES_PORT: 9200
ES_PRESET: single_node_cluster
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: "{{ active_record_encryption.DETERMINISTIC_KEY }}"
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: "{{ active_record_encryption.KEY_DERIVATION_SALT }}"
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: "{{ active_record_encryption.PRIMARY_KEY }}"
SECRET_KEY_BASE: "{{ secret_key_base }}"
SMTP_SERVER: "{{ smtp.SERVER }}"
SMTP_PORT: "{{ smtp.PORT }}"
SMTP_LOGIN: "{{ smtp.LOGIN }}"
SMTP_PASSWORD: "{{ smtp.PASSWORD }}"
SMTP_FROM_ADDRESS: "{{ smtp.FROM_ADDRESS }}"
TRUSTED_PROXY_IP: "127.0.0.1/8,::1/128,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7"
volumes:
- "/home/apps/mastodon/system:/mastodon/public/system:z"
generate_systemd:
new: true
restart_policy: "always"
path: "~/.config/systemd/user/"
force: true
healthcheck: "ps aux | grep '[s]idekiq 8' || false"
- name: Activate sidekiq container service
ansible.builtin.systemd_service:
name: container-sidekiq.service
state: started
enabled: true
scope: user

View File

@@ -0,0 +1,64 @@
---
- name: Populate active record variables
ansible.builtin.include_vars:
file: web.yml
- name: Create Web instance of mastodon
containers.podman.podman_container:
name: mastodon
image: ghcr.io/mastodon/mastodon:v4.5.5
network:
- "{{ mastodon_networks['mastodon_internal']['name'] }}"
- "{{ mastodon_networks['mastodon_external']['name'] }}"
command: "bundle exec puma -C config/puma.rb"
env:
LOCAL_DOMAIN: "wtf.lt"
REDIS_HOST: redis
REDIS_PORT: 6379
DB_HOST: database
DB_NAME: mastodon
DB_USER: "{{ mastodon_database.username }}"
DB_PASS: "{{ mastodon_database.password }}"
DB_PORT: 5432
ES_ENABLED: true
ES_HOST: elasticsearch
ES_PORT: 9200
ES_PRESET: single_node_cluster
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: "{{ active_record_encryption.DETERMINISTIC_KEY }}"
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: "{{ active_record_encryption.KEY_DERIVATION_SALT }}"
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: "{{ active_record_encryption.PRIMARY_KEY }}"
VAPID_PRIVATE_KEY: "{{ vapid.PRIVATE_KEY }}"
VAPID_PUBLIC_KEY: "{{ vapid.PUBLIC_KEY }}"
SECRET_KEY_BASE: "{{ secret_key_base }}"
SMTP_SERVER: "{{ smtp.SERVER }}"
SMTP_PORT: "{{ smtp.PORT }}"
SMTP_LOGIN: "{{ smtp.LOGIN }}"
SMTP_PASSWORD: "{{ smtp.PASSWORD }}"
SMTP_FROM_ADDRESS: "{{ smtp.FROM_ADDRESS }}"
# inspect traefik container and add the IP address here
TRUSTED_PROXY_IP: "127.0.0.1/8,::1/128,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7"
label:
traefik.enable: "true"
traefik.http.routers.mastodon.rule: "Host(`wtf.lt`)"
traefik.http.middlewares.mastodon-https-redirect.redirectscheme.scheme: "https"
traefik.http.routers.mastodon.middlewares: "mastodon-https-redirect"
traefik.http.routers.mastodon-secure.entrypoints: "https"
traefik.http.routers.mastodon-secure.rule: "Host(`wtf.lt`)"
traefik.http.routers.mastodon-secure.tls: "true"
traefik.http.routers.mastodon-secure.tls.certresolver: "lets-encrypt"
traefik.http.services.mastodon.loadbalancer.server.port: "3000"
volumes:
- "/home/apps/mastodon/system:/mastodon/public/system:z"
generate_systemd:
new: true
restart_policy: "always"
path: "~/.config/systemd/user/"
force: true
healthcheck: "curl -s --noproxy localhost localhost:3000/health | grep -q OK"
- name: Activate mastodon web container service
ansible.builtin.systemd_service:
name: container-mastodon.service
state: started
enabled: true
scope: user

View File

@@ -0,0 +1,9 @@
$ANSIBLE_VAULT;1.1;AES256
32653863626339656666343361623163303264353236336331653335626662656632346639383638
3534306263613061306464626534393239343230323766300a353565336131363939366364393232
34326231333631613331636262376639656366343630653263356561633238303866636238623132
3436323865343433610a313532336263353436333430653563613234623364346338633565373039
34323737333136623663383063356533393438353631633538363739646636623363616166333333
38393037306562643665623735313537323761323266613139393237343739353062633637323964
31363364373934326338316238353632633339313032363939343561326463376461373838356136
64326231303565623837

View File

@@ -0,0 +1,19 @@
#SPDX-License-Identifier: MIT-0
---
# vars file for mastodon
mastodon_networks:
mastodon_internal:
name: mastodon_internal
driver: bridge
disable_dns: false
mastodon_external:
name: mastodon_external
driver: bridge
disable_dns: false
mastodon_local_dirs:
- "~/mastodon/postgresql"
- "~/mastodon/redis"
- "~/mastodon/elasticsearch"
- "~/mastodon/system"

View File

@@ -0,0 +1,12 @@
$ANSIBLE_VAULT;1.1;AES256
35666663373862393138616261633564306662353339643838356531653030633462653439613265
6535666636663133313239386230303861613833383532360a373232316566646464306431653632
39306338383138363635376361386435653334313936303335333263653861386533383230633563
3037663336326364320a393763363763376434336361363835363537646661313032396561363462
37336635373630336430316666306336383166626565376365356437353631323734333963353231
62306430383332343666376361636638366430346431326439383836346362313363613235393334
39373366633838356332653137383062323935376365356263313563626530316532623938643262
38356165613734336436646162613163396133613030343131646337623235613764343965646330
37623862306331316436323430306561393465633066333137366237316465396461353262653638
65323336633131613965376162396361316238643639393739303065353833643666633132646630
663664616362346266613837353564393934

View File

@@ -0,0 +1,30 @@
$ANSIBLE_VAULT;1.1;AES256
36623335386437343631383832666131653063623931393164353030643037383034633234663739
6630653465373839666333356435303236663262316630650a363466393765313931633564663937
35303434633134393037363566326561376637666335333438376435333937316665626666633666
3437393834646432320a653530613665393331363031646639353233613330323165303037333039
33343162346132333733343730353735653437363438323030306366643133313964636130376537
61373834343265353465646664626434643665306561376331623031643133643164643233626264
64396531646636613030633130336537373534633137666262623134613138306438363030616432
32306564633762633333383739353061313134386565353264663866316334666663343832323034
64343432363631643731633030613166383136306638373634343431356437326462323431613530
39336130333435373334666638616137326262343565313865333961646238613935306531616332
38393939356461636536316331356137353362613330616231623237393637393163343131313036
66333966383538386430623234356466663564393739393261396664666666386131633030623737
37323364656561393931643132306265393137303938663833613135366561373835643264363161
36396337616430363764356436363632306235623732623633373337613764663665313862633632
62616637653233666437326230326532346165343062326631646534396162346439616666373763
39633833376238376435333730613539626237306536303661373164386133353238353733343866
61383163333538303361376332356538323135376161316363393639633464356333666134313063
61336264653661633839396536623864626339303330383433626136316630373464313136666338
63396362623766383131353935616562353261343336303233363465656535333035616638373539
61343133623232613139333537623532333063356163363963653064666264323162323437623839
33383064653436366338393030613862616638623434376530373132646165316433316439343636
37383437353734316235313931313432326630626362363238636333323662393739303830613463
39393038666339386435313164333731386364316261313932336230346365663236653135653964
37626536373661303834633561353631643265646234346136326563316161323334386631303966
66613830316539393062656138353637656462336462623733386165353934636465373535393837
64373761383832643033353161306339343533326531343332373063343531393432633566663035
38373666343064316435333636333838373539316666386635643233343038333031396261623339
39346665373831353730366532306661343630356666303862626364356439306666346466306130
35653539626132386166386531643366646564633031346264333065333462383063