Upgrade Mastodon from 4.3 to 4.7, deploy on new Ubuntu 24.04 VM #681
No files matched your search
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "mastodon-4",
|
||||
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqBxz0HTAxiUU6VoTTMNj\nonS9GU/RDCq5rIxGd9n89xOoDVb59CgThYgjpthn6T8s1hSkS2Jgi+52S9vlkmXC\nrdr+YhTvqcRuB3w+OMxkaWAwcF6q/c06CzpelyKZ+K9Y1mE7jDVqy9filmZ+p893\nQ5ta4iBg5eE6zsjtVMeTALmsmlwR70vPzZj+VhDeg/TprhFzr44+OB9QNZdFRXSH\n3o0DNhWSvoxUGrt6BOvaNcofYr5XkgP9TLuUZ5p2IZmW58PLSSbTXzPEhdjqACJm\nfCl0ASTHlzbvyTA7bglWuS4HN+VldCts3Y9gVNQ3h6cxfL2aDbWG0Yx2qhAZCOMp\n2wIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||
}
|
||||
@@ -1,114 +1,121 @@
|
||||
{
|
||||
"id": "mastodon",
|
||||
"active_record_encryption_deterministic_key": {
|
||||
"encrypted_data": "2ik8hqK7wrtxyC73DLI8FNezZiWp2rdjwaWZkTUFRj+iwvpSrGVEwMx6uxDI\nWa7zF3p/\n",
|
||||
"iv": "XMp6wqwzStXZx+F3\n",
|
||||
"auth_tag": "vloJOLqEcghfQXOYohVVlg==\n",
|
||||
"encrypted_data": "M7PHYe8qx7TUXpbNMS8slE6p+Naq3WhGklQty8oUJ86cA0hVryqbSySfgBm7\nuEKhTBjO\n",
|
||||
"iv": "tApFi3rs15Y1sCVy\n",
|
||||
"auth_tag": "YZ75dXuxepIm8CK8vOd51A==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"active_record_encryption_key_derivation_salt": {
|
||||
"encrypted_data": "Nq/rHayMYmT/82k3tJUKU8YTvDKUKLoK204aT0CMGZertZaAD3dtA9AkprrA\nPK0D9CdL\n",
|
||||
"iv": "tn9C+igusYMH6GyM\n",
|
||||
"auth_tag": "+ReZRNrfpl6ZDwYQpwm6dw==\n",
|
||||
"encrypted_data": "raLTVbWRr8KRtSL9u2hoZhlcBNzR4qzGssSngIjpVN91ueJF3KRYTf1lyd6O\nt46Il9Ye\n",
|
||||
"iv": "Jhl+LvZlCmJoxMVP\n",
|
||||
"auth_tag": "3RgdNDtaH4eiiQfNHeljTA==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"active_record_encryption_primary_key": {
|
||||
"encrypted_data": "UEDMuKHgZDBhpB9BwbPmtdmIDWHyS9/bSzaEbtTRvLcV8dGOE5q9lDVIIsQp\n2HE0c92p\n",
|
||||
"iv": "tnB0pQ3OGDne3mN/\n",
|
||||
"auth_tag": "kt234ms+bmcxJj/+FH/72Q==\n",
|
||||
"encrypted_data": "nP/pdfTk1VGE+sfAbMq3FN5tyTI4Srpj/szcPDYOU/zfQFRQ3omjSfvOtHFS\nN9XQYPoU\n",
|
||||
"iv": "R4JdQNPjOfqBGUzC\n",
|
||||
"auth_tag": "BW+GO+mX2vpNXLOk3wlcKw==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"paperclip_secret": {
|
||||
"encrypted_data": "AlsnNTRF6GEyHjMHnC4VdzF4swMlppz/Gcp1xr0OuMEgQiOcW1oSZjDRZCRV\nmuGqZXZx64wqZyzTsJZ6ayCLsmWlPq6L21odHWyO+P/C5ubenSXnuCjpUn3/\nHs8WLX3kwVmqCRnVgDl2vEZ5H4XedSLr7R7YM7gQkM0UX4muMDWWnOTR8/x/\ni1ecwBY5RjdewwyR\n",
|
||||
"iv": "RWiLePhFyPekYSl9\n",
|
||||
"auth_tag": "sUq4ZX9CFKPbwDyuKQfNLQ==\n",
|
||||
"encrypted_data": "plu8NMS/EuYAOxepD1lHbfVnzDcwmqFy1LhUKKUhqiQUlanzlZ2kYga8dy0D\n8s1XcVpw8Ei8Pz3LOjuTNfi/gE6yvinbJpxXFRgy2r6iUmoTDaSyk3wyybSN\nQkPPr5p79sJiybtJbgJZSLSylxswp0zsXYNiomoMXaxkGVoLRAEnZ18yKHrR\nzr6EbJp9IMDVOhQe\n",
|
||||
"iv": "dyThHZkYejBTYV7s\n",
|
||||
"auth_tag": "mjAiHvv40dcS5uDMz+CfGQ==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"secret_key_base": {
|
||||
"encrypted_data": "K5CmIXFa9mS4/dODBQAN9Bw0SFpbLiZAB8ewiYpkB8NDXP6X/BX8aDjW2Y4F\ncMvpFyiFldRBhrh1MSKTVYQEoJ3JhlNL9HCdPsAYbBEW70AuEBpHvOtD5OxH\nqgbH4Reuk6JX5AI8SwDD3zGrdT12mTFVNgSujzuZMvpi1Sro2HtRGAkjmnaa\nMGKrBV21O1CREJJg\n",
|
||||
"iv": "/yMMmz1YtKIs5HSd\n",
|
||||
"auth_tag": "WXgIVWjIdbMFlJhTD5J0JQ==\n",
|
||||
"encrypted_data": "+3rZASvdx2B8if9UxJCTJC8OoaOLink/6muPcRv7DNedqF2fmAajI3sJuKYB\nslLUTweW3T+IVHnzT8RiNiY8mZ81ivkyQwqtl0qnfwrWTDB3auPdlZTIxSfn\nDz4a/Z4it8ewrPXeFfsZgxJebG313JB4EQN/LBHgJMBKkVeuDS4tl1zwSt4C\njEv01JO/7HXLVdGu\n",
|
||||
"iv": "+CWPVenB0YLeUVF+\n",
|
||||
"auth_tag": "0ZDAgVX7k/1JNDvzK7/Hxw==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"otp_secret": {
|
||||
"encrypted_data": "OPLnYRySSIDOcVHy2A5V+pCrz9zVIPjdpAGmCdgQkXtJfsS9NzNtxOPwrXo6\nuQlV9iPjr1Y9ljGKYytbF0fPgAa5q6Z1oHMY9vOGs/LGKj8wHDmIvxQ+Gil1\nC+dZEePmqGaySlNSB/gNzcFIvjBH3mDxHJJe9hDxSv5miNS9l9f3UvQeLP2M\nU7/aHKagL9ZHOp/d\n",
|
||||
"iv": "wqJBLdZhJ7M/KRG9\n",
|
||||
"auth_tag": "dv5YyZszZCrRnTleaiGd4A==\n",
|
||||
"encrypted_data": "8xVxIgJLV4fM2DvNBeVwUTEuyf9TsAgiWrKgoj/dKmFriiZTMrY40qkoPJbP\nEI3NCK8Pvt1MF5izT/6jzxEjXEZRo3kWk1x3QqIbLmo/z6k4GC0JhAO8xDKL\nopGQBOj0Bjte3xsz/vBFCgmqpC1WQe/FpCyFVT1r0uVwAUkMiM/7McnRVmKJ\nPS59QJuuV1DtI6b+\n",
|
||||
"iv": "j2tC9oc6U6bjV5BJ\n",
|
||||
"auth_tag": "/Hi9sxV3aN6BR5Ixdf78DQ==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"aws_access_key_id": {
|
||||
"encrypted_data": "A1/gfcyrwT6i9W6aGTJ8pH4Dm4o8ACDxvooDroA/2N0szOiNyiYX\n",
|
||||
"iv": "JNvf21KhdM3yoLGt\n",
|
||||
"auth_tag": "2xaZql1ymPYuXuvXzT3ymA==\n",
|
||||
"encrypted_data": "71TLwj7sYmHAm/cEX6lKE8MWDlceW5S0hrPLNVzVZ7IimjTNYf4g\n",
|
||||
"iv": "DoSmqv6owgIL8+be\n",
|
||||
"auth_tag": "ZcO902nm+MbP4+mwLACDvQ==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"aws_secret_access_key": {
|
||||
"encrypted_data": "T1tc01nACxhDgygKaiAq3LChGYSgmW8LAwr1aSxXmJ5D2NtypJDikiHrJbFZ\nfWFgm1qe4L8iD/k5+ro=\n",
|
||||
"iv": "FDTPQQDLUMKW7TXx\n",
|
||||
"auth_tag": "msY6PFFYhlwQ0X7gekSDiw==\n",
|
||||
"encrypted_data": "6VOYHuZ27cqx5rfrWeKfUyX6lpSI9/o7MXuj/ah7ZTKSwx6GUbzbe3hzZJcM\nzlDjF8WkIkOwUt/yK5I=\n",
|
||||
"iv": "F7wyRALeMvPec7i6\n",
|
||||
"auth_tag": "I27zZeNdqetp9+Pvor7FVw==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"ldap_bind_dn": {
|
||||
"encrypted_data": "C/YNROVyOxmR4O2Cy52TX41EKli2bCOMzwYD+6Hz/SiKkgidnKUHlvHlbTDq\nkWwlRDM2o8esOCKaEAGPNWcNc9IHlaSsfwhr4YWnwe0=\n",
|
||||
"iv": "QCQF0+vH+//+nDxr\n",
|
||||
"auth_tag": "a0PbyO/7wjufqH2acDCqmQ==\n",
|
||||
"encrypted_data": "d5AxFLbM5mkQ42Ev3jLF6divhVGRS29pf4V1HLT/EZoeTaY0Ag6+aRujP9ri\nHDi5j+VRaKNMtfK1NzQKl6XiCj0oGdO1EsRynpxXyJ0=\n",
|
||||
"iv": "T4Qz2KrB30La0dj/\n",
|
||||
"auth_tag": "4I+ySAVvfFDDnfipb+JjDA==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"ldap_password": {
|
||||
"encrypted_data": "SqwKeiyzfvvZGqH5gi35BdW3W+Fo/AQQjso1Yfp2XA==\n",
|
||||
"iv": "md2/etFJ1r/BKaYg\n",
|
||||
"auth_tag": "OlCCOoYSD7ukdH2yWCd6KA==\n",
|
||||
"encrypted_data": "2V7nesfImnY6DooFctBupXKyexLqTUUoY5M7wQE0FA==\n",
|
||||
"iv": "wjRF6W7JkUUS6Qn8\n",
|
||||
"auth_tag": "PhuKjWIla3yFCprFgzxilA==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"smtp_user_name": {
|
||||
"encrypted_data": "0kzppmSSUg7lEyYnI5a0nf+xO0vSVx88rbxI+niIdzFOOBKSIL6uVHJ340dw\nMQ==\n",
|
||||
"iv": "lQR77ETTtIIyaG1r\n",
|
||||
"auth_tag": "smF2HRg8WdmD+MWwkT3TqA==\n",
|
||||
"encrypted_data": "rQR5ut5VCbQf3dLz6els3BSU3Lj1dZp0k6EaEZnM2E41HrQbMCAgMWrepTaO\nCQ==\n",
|
||||
"iv": "5e/KzhAz6ALZzxOm\n",
|
||||
"auth_tag": "wBJLKVHyB1JKeZ9hS8uUIQ==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"smtp_password": {
|
||||
"encrypted_data": "1i0m9qiZA/8k8fMKo+04uyndl1UhagtHweBFICIorWALkB68edjb8OhUDxv9\nTubiXYRC\n",
|
||||
"iv": "IU2x4ips9HWmKoxi\n",
|
||||
"auth_tag": "BZJTDfPBvt8cf6/MbKzUJQ==\n",
|
||||
"encrypted_data": "AYFleIGUXYZGqSXoDhJB9CG8jNlM1libXzxByDiOPxJH3q5vpGYl+ZThGQZ3\n1HFfKhR/\n",
|
||||
"iv": "Qrvt1HLaHBqHwApE\n",
|
||||
"auth_tag": "auqwRDScQfGe42Olhj/y7g==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"vapid_private_key": {
|
||||
"encrypted_data": "+LmySMvzrV3z2z7BmJG9hpvkL06mGc87RG20XQhhdAJ2Z/5uMMjev2pUf7du\ntv2qvDJAimhkZajuDGL9R3eq\n",
|
||||
"iv": "Mg7NhPl31O6Z4P+v\n",
|
||||
"auth_tag": "qYWPInhgoWAjg0zQ+XXt5w==\n",
|
||||
"encrypted_data": "PRNWILa/ipj00zXrCknF0PZlpvPPPNtGgPuJS61Q8I4+XK517cAaDQypQFUa\nznm2KfQvHWDmQPRfS/oRYIk1\n",
|
||||
"iv": "EBEzvMfR8J6X8o9J\n",
|
||||
"auth_tag": "qECmv9fOw2PKgbxIYaWEnw==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"vapid_public_key": {
|
||||
"encrypted_data": "NOyc+Cech9qG2HhnhajDaJMWd1OU5Rp6hws6i4xF5mLPePMJ9mJTqzklkuMK\npYSEdtcxA3KmDt1HrFxfezYUc9xO9pvlm0BPA7XAFmF/PU7/AJbFqgPU6pX/\ntSDLSdFuMB3ky+cl4DJi+O4=\n",
|
||||
"iv": "rgUglYiHB/mhqGha\n",
|
||||
"auth_tag": "DEX7hdNsNLi/LIrMkdUe/Q==\n",
|
||||
"encrypted_data": "A+yqJ64L2rrqSJ4WyCVh6rXJG9aMSyr/+11pvb8w8al3Ei69YoeX1DeWeD6J\nXgogGJDCoucoCAlcx9tFhmWpR9050d+d2Fuz2RvvElUYUACdSpzlKYcJ1fkl\nRSjUVH69EePjg3GTxlkCDiA=\n",
|
||||
"iv": "hEjJ7NWlRjlGtFbQ\n",
|
||||
"auth_tag": "2WGbglPqBR00UINDVr38hA==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"s3_key_id": {
|
||||
"encrypted_data": "rPVzrYYIbcM+ssVpdL6wpCTdzLIEKXke1+eMlPLMG2gPuoh+W3eO3nFGb/s2\n",
|
||||
"iv": "/qI8F9cvnfKG7ZXE\n",
|
||||
"auth_tag": "z1+MPdkO/+SCaag2ULelPg==\n",
|
||||
"encrypted_data": "Jln2B+YjH6rWfgVzMmDg6oBB1PEZ0stiNFKEpTTSkht68oGXPVYOm40m7+/Q\n",
|
||||
"iv": "Sz7de5LhoH6FFs93\n",
|
||||
"auth_tag": "aZJjE5GCPy2QAFCHhnp6oQ==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"s3_secret_key": {
|
||||
"encrypted_data": "RMnB9kZ+slbQXfpo0udYld6S1QqBxqM1YbszdLfSAdKK9I0J3Kmvh/CQ5Fbx\nyov6LClmsl1rjtH16r7cY32M4Woq+6miERdtecyDrrYkNHz0xkA=\n",
|
||||
"iv": "pO7bm3aOtjuwYjG/\n",
|
||||
"auth_tag": "SRvn4z1+Vd5VAGgjG64s+Q==\n",
|
||||
"encrypted_data": "Bjpc0XCQyPq3ZVggp2GHPDUHiOPX3UH6tNFeJE9lkqL7NSRmQ5r/Do7oDjQB\nT2Es7NL3rFLdVoV6tRRchkUDFzgyr2eSvEHkproU44FTTFmgDN0=\n",
|
||||
"iv": "HEkOIrKktAezN1AK\n",
|
||||
"auth_tag": "s54GLjslaf0e30MzW3kY5g==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
},
|
||||
"repo_deploy_key": {
|
||||
"encrypted_data": "hI6a++CCP2/wn5OM86neYUyzFlvD1/w3VaDPB93cPkCqp7UJlj4mOl1J3Gpd\n4Tej/dpsEFiEWP2D15bMHPm5eD8YtD0iueRsTs7TVsgAwWcPIkBV52QHKjoB\nyn6FlA8f6wjF1D4IKhdSbBl2Se0gFPHT3FMy6NkV0dyUB60umMZhaQTS0h9+\ngbi6AYYQSxs3YkfAcQa7iyAXWSw1M4EsrrN2EQ14KN5RTjv24hgNGgUnINMa\nc7dVnz31wIdLfLZy2SlqNQqgwyz8KRXnDWdwnbvwNrJ1HMwNARabDnySUTB9\n03nExQnxG+c3+ioC7KSO++QATC9m0iWjx93m7S7VcbCwdpBZsswztQ/ix8AL\n6CddyLpcK80QrFPrSb2UjFtZuLNuX/Cbzrmm73MYqi/WKfWstKnyFBfkAJUA\nK8HnFU6gmvxyrgQp5ZI/1FNegr67sQlE0dhTYUcps5ZhpJ7ppJX4Fb3yq//8\n8NXEVxGrEwxCAMQEU5HlbBLXTLcTtLhujppPkdp4nYLdiWIMGIqnvOoeJi4n\nTg18xwdMN9G0OMH818Pj/LRBVfxzStbd1ZkemQw6\n",
|
||||
"iv": "8d8CQGLoNlIyZT6h\n",
|
||||
"auth_tag": "J9K5wCJ0bZl5uI2PM9+gag==\n",
|
||||
"version": 3,
|
||||
"cipher": "aes-256-gcm"
|
||||
}
|
||||
|
||||
+1
-1
Submodule nodes updated: b3b5042655...58e8fb83fd.
+4
-1
@@ -1,8 +1,11 @@
|
||||
name "mastodon"
|
||||
|
||||
default_attributes 'kosmos-mastodon' => {
|
||||
'deploy' => true
|
||||
}
|
||||
|
||||
run_list %w(
|
||||
role[postgresql_client]
|
||||
kosmos-mastodon::libretranslate
|
||||
kosmos-mastodon
|
||||
kosmos-mastodon::backup
|
||||
)
|
||||
@@ -298,7 +298,9 @@ execute "bundle install" do
|
||||
environment deploy_env
|
||||
user deploy_user
|
||||
cwd deploy_path
|
||||
command "bundle install --without development,test --deployment"
|
||||
command "bundle config set --local deployment true && " \
|
||||
"bundle config set --local without 'development test' && " \
|
||||
"bundle install"
|
||||
end
|
||||
|
||||
execute 'rake db:migrate' do
|
||||
|
||||
@@ -1,13 +1,37 @@
|
||||
node.default["kosmos-mastodon"]["repo"] = "https://gitea.kosmos.org/kosmos/mastodon.git"
|
||||
node.default["kosmos-mastodon"]["revision"] = "production-4.3"
|
||||
node.default["kosmos-mastodon"]["repo"] = "git@gitea.kosmos.org:kosmos/mastodon.git"
|
||||
node.default["kosmos-mastodon"]["revision"] = "production-4.7"
|
||||
node.default["kosmos-mastodon"]["directory"] = "/opt/mastodon"
|
||||
node.default["kosmos-mastodon"]["bind_ip"] = "127.0.0.1"
|
||||
node.default["kosmos-mastodon"]["app_port"] = 3000
|
||||
node.default["kosmos-mastodon"]["streaming_port"] = 4000
|
||||
node.default["kosmos-mastodon"]["domain"] = "kosmos.social"
|
||||
node.default["kosmos-mastodon"]["alternate_domains"] = []
|
||||
node.default["kosmos-mastodon"]["redis_url"] = "redis://localhost:6379/0"
|
||||
node.default["kosmos-mastodon"]["sidekiq_threads"] = 25
|
||||
|
||||
# Only run the Mastodon deployment (code, build, migrations, services) when this
|
||||
# is true. Set to false to only install the runtime dependencies.
|
||||
node.default["kosmos-mastodon"]["deploy"] = true
|
||||
|
||||
# Only check out and build the application (no migrations, no services) when
|
||||
# this is true. Implied by `deploy`. Useful to pre-stage a deployment without
|
||||
# touching the database.
|
||||
node.default["kosmos-mastodon"]["build"] = true
|
||||
|
||||
# Runtime versions
|
||||
node.default["kosmos-mastodon"]["nodejs_version"] = "24.21.0"
|
||||
node.default["kosmos-mastodon"]["ruby_version"] = "4.0.7"
|
||||
node.default["kosmos-mastodon"]["ruby_build_version"] = "v20260924"
|
||||
|
||||
# SSH deploy key access to the (private) repository. The private key is stored
|
||||
# in the credentials/mastodon data bag as `repo_deploy_key`; this is the pinned
|
||||
# host key of gitea.kosmos.org.
|
||||
node.default["kosmos-mastodon"]["gitea_ssh_host_key"] =
|
||||
"gitea.kosmos.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJycWc3U9P/6BzE0HcPiTdmaDN8zKRx+0/jGXYuKiwx7"
|
||||
|
||||
# External Redis cluster (see the kosmos_redis cookbook)
|
||||
node.default["kosmos-mastodon"]["redis_server_role"] = "redis_server"
|
||||
node.default["kosmos-mastodon"]["redis_port"] = 6379
|
||||
node.default["kosmos-mastodon"]["redis_db"] = 2
|
||||
node.default["kosmos-mastodon"]["allowed_private_addresses"] = "127.0.0.1"
|
||||
|
||||
node.default["kosmos-mastodon"]["onion_address"] = nil
|
||||
@@ -25,6 +49,10 @@ node.default["kosmos-mastodon"]["sso_account_reset_password_url"] = "https://acc
|
||||
node.default["kosmos-mastodon"]["sso_account_resend_confirmation_url"] = "https://accounts.kosmos.org/users/confirmation/new"
|
||||
|
||||
node.default["kosmos-mastodon"]["default_locale"] = "en"
|
||||
# From Mastodon 4.4 on, DEFAULT_LOCALE no longer overrides the browser language
|
||||
# of unauthenticated users unless this is set to true.
|
||||
node.default["kosmos-mastodon"]["force_default_locale"] = true
|
||||
# Mastodon 4.6 introduced optional email subscriptions which can cause
|
||||
# additional outgoing mail/costs. Disabled by default.
|
||||
node.default["kosmos-mastodon"]["disable_email_subscriptions"] = true
|
||||
node.default["kosmos-mastodon"]["libre_translate_endpoint"] = nil
|
||||
|
||||
node.override["redisio"]["version"] = "6.2.6"
|
||||
@@ -6,11 +6,8 @@ description 'Installs/Configures Mastodon'
|
||||
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
||||
version '0.2.1'
|
||||
|
||||
depends 'backup'
|
||||
depends 'elasticsearch'
|
||||
depends 'java'
|
||||
depends 'firewall'
|
||||
depends 'redisio'
|
||||
depends 'postgresql'
|
||||
depends 'kosmos-nodejs'
|
||||
depends 'kosmos_openresty'
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#
|
||||
# Cookbook Name:: kosmos-mastodon
|
||||
# Recipe:: backup
|
||||
#
|
||||
|
||||
postgresql_data_bag_item = data_bag_item('credentials', 'postgresql')
|
||||
|
||||
unless node.chef_environment == "development"
|
||||
node.override['backup']['s3']['keep'] = 1
|
||||
node.override["backup"]["postgresql"]["host"] = "pg.kosmos.local"
|
||||
node.override["backup"]["postgresql"]["databases"]["mastodon"] = {
|
||||
username: "mastodon",
|
||||
password: postgresql_data_bag_item['mastodon_user_password']
|
||||
}
|
||||
|
||||
include_recipe "backup"
|
||||
end
|
||||
@@ -0,0 +1,193 @@
|
||||
#
|
||||
# Cookbook Name:: kosmos-mastodon
|
||||
# Recipe:: build
|
||||
#
|
||||
# Checks out and builds the application without running migrations or starting
|
||||
# any services, so a deployment can be pre-staged before the maintenance
|
||||
# window. The build is skipped while the checked-out revision is unchanged.
|
||||
#
|
||||
|
||||
require 'uri'
|
||||
|
||||
postgresql_credentials = data_bag_item('credentials', 'postgresql')
|
||||
|
||||
mastodon_path = node["kosmos-mastodon"]["directory"]
|
||||
mastodon_user = "mastodon"
|
||||
mastodon_home = "/home/#{mastodon_user}"
|
||||
|
||||
ruby_version = node["kosmos-mastodon"]["ruby_version"]
|
||||
ruby_path = "/opt/ruby_build/builds/#{ruby_version}"
|
||||
|
||||
# External Redis cluster (see the kosmos_redis cookbook)
|
||||
redis_host = search(:node, "role:#{node['kosmos-mastodon']['redis_server_role']}").first&.dig("knife_zero", "host")
|
||||
|
||||
if redis_host.nil?
|
||||
Chef::Log.fatal("No node found with '#{node['kosmos-mastodon']['redis_server_role']}' role. Stopping here.")
|
||||
return
|
||||
end
|
||||
|
||||
redis_password = URI.encode_www_form_component(data_bag_item('credentials', 'redis')['password'])
|
||||
redis_url = "redis://:#{redis_password}@#{redis_host}:#{node['kosmos-mastodon']['redis_port']}/#{node['kosmos-mastodon']['redis_db']}"
|
||||
|
||||
rails_env = node.chef_environment == "development" ? "development" : "production"
|
||||
deploy_env = {
|
||||
# FIXME: /usr/bin was missing from PATH when running `yarn install`
|
||||
"PATH" => "#{ruby_path}/bin:/usr/bin:$PATH",
|
||||
"HOME" => mastodon_home,
|
||||
"RAILS_ENV" => rails_env,
|
||||
"NODE_ENV" => rails_env,
|
||||
"COREPACK_ENABLE_DOWNLOAD_PROMPT" => "0"
|
||||
}
|
||||
|
||||
# Skip the build while the checked-out revision is unchanged
|
||||
build_uptodate = "test -f #{mastodon_path}/tmp/built-revision && " \
|
||||
"test \"$(cat #{mastodon_path}/tmp/built-revision)\" = \"$(git -C #{mastodon_path} rev-parse HEAD)\""
|
||||
|
||||
credentials = data_bag_item('credentials', 'mastodon')
|
||||
|
||||
# The repository is private; clone it with a read-only SSH deploy key kept in
|
||||
# the mastodon user's home (outside the clone destination).
|
||||
directory "#{mastodon_home}/.ssh" do
|
||||
owner mastodon_user
|
||||
group mastodon_user
|
||||
mode "0700"
|
||||
end
|
||||
|
||||
file "#{mastodon_home}/.ssh/id_ed25519" do
|
||||
# OpenSSH's PEM parser rejects a private key without a trailing newline
|
||||
content lazy { credentials["repo_deploy_key"].to_s.chomp + "\n" }
|
||||
owner mastodon_user
|
||||
group mastodon_user
|
||||
mode "0600"
|
||||
sensitive true
|
||||
end
|
||||
|
||||
file "#{mastodon_home}/.ssh/known_hosts" do
|
||||
content "#{node['kosmos-mastodon']['gitea_ssh_host_key']}\n"
|
||||
owner mastodon_user
|
||||
group mastodon_user
|
||||
mode "0644"
|
||||
end
|
||||
|
||||
file "#{mastodon_home}/.ssh/config" do
|
||||
content <<-EOF
|
||||
Host gitea.kosmos.org
|
||||
IdentityFile #{mastodon_home}/.ssh/id_ed25519
|
||||
IdentitiesOnly yes
|
||||
StrictHostKeyChecking yes
|
||||
UserKnownHostsFile #{mastodon_home}/.ssh/known_hosts
|
||||
EOF
|
||||
owner mastodon_user
|
||||
group mastodon_user
|
||||
mode "0600"
|
||||
end
|
||||
|
||||
# Chef's git resource silently skips cloning when the destination is non-empty
|
||||
# and not a git clone, so make sure we start from a clean directory.
|
||||
execute "clear non-git repository directory" do
|
||||
command "find #{mastodon_path} -mindepth 1 -delete"
|
||||
only_if { ::Dir.exist?(mastodon_path) && !::File.exist?("#{mastodon_path}/.git") }
|
||||
end
|
||||
|
||||
git mastodon_path do
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
|
||||
repository node["kosmos-mastodon"]["repo"]
|
||||
revision node["kosmos-mastodon"]["revision"]
|
||||
environment "GIT_SSH_COMMAND" =>
|
||||
"ssh -i #{mastodon_home}/.ssh/id_ed25519 -o IdentitiesOnly=yes " \
|
||||
"-o StrictHostKeyChecking=yes -o UserKnownHostsFile=#{mastodon_home}/.ssh/known_hosts"
|
||||
end
|
||||
|
||||
ldap_config = {
|
||||
host: "ldap.kosmos.local",
|
||||
port: 389,
|
||||
method: "plain",
|
||||
base: "ou=kosmos.org,cn=users,dc=kosmos,dc=org",
|
||||
bind_dn: credentials["ldap_bind_dn"],
|
||||
password: credentials["ldap_password"],
|
||||
uid: "cn",
|
||||
mail: "mail",
|
||||
search_filter: "(&(|(cn=%{email})(mail=%{email}))(serviceEnabled=mastodon))",
|
||||
uid_conversion_enabled: "true",
|
||||
uid_conversion_search: "-",
|
||||
uid_conversion_replace: "_"
|
||||
}
|
||||
|
||||
template "#{mastodon_path}/.env.#{rails_env}" do
|
||||
source "env.erb"
|
||||
mode "0640"
|
||||
owner mastodon_user
|
||||
group mastodon_user
|
||||
sensitive true
|
||||
variables redis_url: redis_url,
|
||||
domain: node["kosmos-mastodon"]["domain"],
|
||||
alternate_domains: node["kosmos-mastodon"]["alternate_domains"],
|
||||
active_record_encryption_deterministic_key: credentials["active_record_encryption_deterministic_key"],
|
||||
active_record_encryption_key_derivation_salt: credentials["active_record_encryption_key_derivation_salt"],
|
||||
active_record_encryption_primary_key: credentials["active_record_encryption_primary_key"],
|
||||
paperclip_secret: credentials['paperclip_secret'],
|
||||
secret_key_base: credentials['secret_key_base'],
|
||||
ldap: ldap_config,
|
||||
smtp_login: credentials['smtp_user_name'],
|
||||
smtp_password: credentials['smtp_password'],
|
||||
smtp_from_address: "mail@#{node['kosmos-mastodon']['domain']}",
|
||||
s3_endpoint: node["kosmos-mastodon"]["s3_endpoint"],
|
||||
s3_region: node["kosmos-mastodon"]["s3_region"],
|
||||
s3_bucket: node["kosmos-mastodon"]["s3_bucket"],
|
||||
s3_alias_host: node["kosmos-mastodon"]["s3_alias_host"],
|
||||
aws_access_key_id: credentials['s3_key_id'],
|
||||
aws_secret_access_key: credentials['s3_secret_key'],
|
||||
vapid_private_key: credentials['vapid_private_key'],
|
||||
vapid_public_key: credentials['vapid_public_key'],
|
||||
db_pass: postgresql_credentials['mastodon_user_password'],
|
||||
db_host: "pg.kosmos.local",
|
||||
sso_account_sign_up_url: node["kosmos-mastodon"]["sso_account_sign_up_url"],
|
||||
sso_account_reset_password_url: node["kosmos-mastodon"]["sso_account_reset_password_url"],
|
||||
sso_account_resend_confirmation_url: node["kosmos-mastodon"]["sso_account_resend_confirmation_url"],
|
||||
default_locale: node["kosmos-mastodon"]["default_locale"],
|
||||
force_default_locale: node["kosmos-mastodon"]["force_default_locale"],
|
||||
disable_email_subscriptions: node["kosmos-mastodon"]["disable_email_subscriptions"],
|
||||
allowed_private_addresses: node["kosmos-mastodon"]["allowed_private_addresses"],
|
||||
libre_translate_endpoint: node["kosmos-mastodon"]["libre_translate_endpoint"]
|
||||
notifies :run, "execute[restart mastodon services]", :delayed if node["kosmos-mastodon"]["deploy"]
|
||||
end
|
||||
|
||||
execute "bundle install" do
|
||||
environment deploy_env.merge("BUNDLE_BUILD__CHARLOCK_HOLMES" => "--with-cxxflags=-std=c++17")
|
||||
user mastodon_user
|
||||
cwd mastodon_path
|
||||
command "bundle config set --local deployment true && " \
|
||||
"bundle config set --local without 'development test' && " \
|
||||
"bundle install"
|
||||
not_if build_uptodate
|
||||
end
|
||||
|
||||
execute "yarn install" do
|
||||
environment deploy_env
|
||||
user mastodon_user
|
||||
cwd mastodon_path
|
||||
command "yarn install --immutable"
|
||||
not_if build_uptodate
|
||||
end
|
||||
|
||||
execute "rake assets:precompile" do
|
||||
environment deploy_env
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
cwd mastodon_path
|
||||
command "bundle exec rake assets:precompile"
|
||||
not_if build_uptodate
|
||||
notifies :run, "execute[record built revision]", :immediately
|
||||
end
|
||||
|
||||
# Record the built revision. Runs as the mastodon user so git accepts the repo
|
||||
# (a root-run `git` would refuse due to dubious ownership).
|
||||
execute "record built revision" do
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
cwd mastodon_path
|
||||
command "git rev-parse HEAD > tmp/built-revision"
|
||||
action :nothing
|
||||
end
|
||||
@@ -3,316 +3,10 @@
|
||||
# Recipe:: default
|
||||
#
|
||||
|
||||
node.override["kosmos_nodejs"]["version"] = "18.20.8"
|
||||
include_recipe "kosmos-mastodon::dependencies"
|
||||
|
||||
include_recipe "kosmos-nodejs"
|
||||
include_recipe "java"
|
||||
include_recipe 'redisio::default'
|
||||
include_recipe 'redisio::enable'
|
||||
include_recipe 'firewall'
|
||||
# Check out and build the application without touching the database.
|
||||
include_recipe "kosmos-mastodon::build" if node["kosmos-mastodon"]["build"] || node["kosmos-mastodon"]["deploy"]
|
||||
|
||||
elasticsearch_user 'elasticsearch'
|
||||
|
||||
elasticsearch_install 'elasticsearch' do
|
||||
type 'package'
|
||||
# The current version of the elasticsearch cookbook doesn't like versions
|
||||
# it doesn't know about. This would still be installing the default (7.17.9)
|
||||
# on a new machine, but it doesn't upgrade the package
|
||||
download_url 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.7-amd64.deb'
|
||||
# SHA256
|
||||
download_checksum '5c588d779023672ba4e315e7cd4db068ac60a38873a35973574a1cae858c2030'
|
||||
action :install
|
||||
end
|
||||
|
||||
elasticsearch_configure 'elasticsearch' do
|
||||
allocated_memory node["kosmos-mastodon"]["elasticsearch"]["allocated_memory"]
|
||||
|
||||
jvm_options %w(
|
||||
-XX:+AlwaysPreTouch
|
||||
-server
|
||||
-Xss1m
|
||||
-Djava.awt.headless=true
|
||||
-Dfile.encoding=UTF-8
|
||||
-Djna.nosys=true
|
||||
-XX:-OmitStackTraceInFastThrow
|
||||
-Dio.netty.noUnsafe=true
|
||||
-Dio.netty.noKeySetOptimization=true
|
||||
-Dio.netty.recycler.maxCapacityPerThread=0
|
||||
-XX:+HeapDumpOnOutOfMemoryError
|
||||
)
|
||||
end
|
||||
|
||||
elasticsearch_service 'elasticsearch'
|
||||
|
||||
postgresql_credentials = data_bag_item('credentials', 'postgresql')
|
||||
|
||||
mastodon_path = node["kosmos-mastodon"]["directory"]
|
||||
mastodon_user = "mastodon"
|
||||
|
||||
bind_ip = if node.chef_environment == "production"
|
||||
node["knife_zero"]["host"]
|
||||
else
|
||||
node["kosmos-mastodon"]["bind_ip"]
|
||||
end
|
||||
|
||||
group mastodon_user do
|
||||
gid 62786
|
||||
end
|
||||
|
||||
user mastodon_user do
|
||||
comment "mastodon user"
|
||||
uid 62786
|
||||
gid 62786
|
||||
shell "/bin/bash"
|
||||
home mastodon_path
|
||||
end
|
||||
|
||||
package %w(build-essential imagemagick ffmpeg libxml2-dev libxslt1-dev file git
|
||||
curl pkg-config libprotobuf-dev protobuf-compiler libidn11
|
||||
libidn11-dev libjemalloc2 libpq-dev)
|
||||
|
||||
ruby_version = "3.3.5"
|
||||
|
||||
ruby_path = "/opt/ruby_build/builds/#{ruby_version}"
|
||||
bundle_path = "#{ruby_path}/bin/bundle"
|
||||
|
||||
ruby_build_install 'v20231025'
|
||||
ruby_build_definition ruby_version do
|
||||
prefix_path ruby_path
|
||||
end
|
||||
|
||||
execute "systemctl daemon-reload" do
|
||||
command "systemctl daemon-reload"
|
||||
action :nothing
|
||||
end
|
||||
|
||||
# mastodon-web service
|
||||
#
|
||||
template "/lib/systemd/system/mastodon-web.service" do
|
||||
source "mastodon-web.systemd.service.erb"
|
||||
variables user: mastodon_user,
|
||||
app_dir: mastodon_path,
|
||||
bind: bind_ip,
|
||||
port: node["kosmos-mastodon"]["app_port"],
|
||||
bundle_path: bundle_path
|
||||
notifies :run, "execute[systemctl daemon-reload]", :immediately
|
||||
notifies :restart, "service[mastodon-web]", :delayed
|
||||
end
|
||||
|
||||
# mastodon-sidekiq service
|
||||
#
|
||||
template "/lib/systemd/system/mastodon-sidekiq.service" do
|
||||
source "mastodon-sidekiq.systemd.service.erb"
|
||||
variables user: mastodon_user,
|
||||
app_dir: mastodon_path,
|
||||
bundle_path: bundle_path,
|
||||
sidekiq_threads: node["kosmos-mastodon"]["sidekiq_threads"]
|
||||
notifies :run, "execute[systemctl daemon-reload]", :immediately
|
||||
notifies :restart, "service[mastodon-sidekiq]", :delayed
|
||||
end
|
||||
|
||||
# mastodon-sidekiq-scheduler service
|
||||
#
|
||||
template "/lib/systemd/system/mastodon-sidekiq-scheduler.service" do
|
||||
source "mastodon-sidekiq-scheduler.systemd.service.erb"
|
||||
variables user: mastodon_user,
|
||||
app_dir: mastodon_path,
|
||||
bundle_path: bundle_path,
|
||||
sidekiq_threads: 1
|
||||
notifies :run, "execute[systemctl daemon-reload]", :immediately
|
||||
notifies :restart, "service[mastodon-sidekiq-scheduler]", :delayed
|
||||
end
|
||||
|
||||
# mastodon-streaming service
|
||||
#
|
||||
template "/lib/systemd/system/mastodon-streaming.service" do
|
||||
source "mastodon-streaming.systemd.service.erb"
|
||||
variables user: mastodon_user,
|
||||
app_dir: mastodon_path,
|
||||
bind: bind_ip,
|
||||
port: node["kosmos-mastodon"]["streaming_port"]
|
||||
notifies :run, "execute[systemctl daemon-reload]", :immediately
|
||||
notifies :restart, "service[mastodon-streaming]", :delayed
|
||||
end
|
||||
|
||||
rails_env = node.chef_environment == "development" ? "development" : "production"
|
||||
deploy_env = {
|
||||
# FIXME: /usr/bin was missing from PATH when running `yarn install`
|
||||
"PATH" => "#{ruby_path}/bin:/usr/bin:$PATH",
|
||||
"HOME" => mastodon_path,
|
||||
"RAILS_ENV" => rails_env,
|
||||
"NODE_ENV" => rails_env,
|
||||
"SKIP_POST_DEPLOYMENT_MIGRATIONS" => "true"
|
||||
}
|
||||
|
||||
git mastodon_path do
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
|
||||
repository node["kosmos-mastodon"]["repo"]
|
||||
revision node["kosmos-mastodon"]["revision"]
|
||||
# Restart services on deployments
|
||||
notifies :run, "execute[restart mastodon services]", :delayed
|
||||
end
|
||||
|
||||
execute "restart mastodon services" do
|
||||
command "true"
|
||||
action :nothing
|
||||
notifies :restart, "service[mastodon-web]", :delayed
|
||||
notifies :restart, "service[mastodon-sidekiq]", :delayed
|
||||
notifies :restart, "service[mastodon-sidekiq-scheduler]", :delayed
|
||||
notifies :restart, "service[mastodon-streaming]", :delayed
|
||||
end
|
||||
|
||||
credentials = data_bag_item('credentials', 'mastodon')
|
||||
|
||||
ldap_config = {
|
||||
host: "ldap.kosmos.local",
|
||||
port: 389,
|
||||
method: "plain",
|
||||
base: "ou=kosmos.org,cn=users,dc=kosmos,dc=org",
|
||||
bind_dn: credentials["ldap_bind_dn"],
|
||||
password: credentials["ldap_password"],
|
||||
uid: "cn",
|
||||
mail: "mail",
|
||||
search_filter: "(&(|(cn=%{email})(mail=%{email}))(serviceEnabled=mastodon))",
|
||||
uid_conversion_enabled: "true",
|
||||
uid_conversion_search: "-",
|
||||
uid_conversion_replace: "_"
|
||||
}
|
||||
|
||||
template "#{mastodon_path}/.env.#{rails_env}" do
|
||||
source "env.erb"
|
||||
mode "0640"
|
||||
owner mastodon_user
|
||||
group mastodon_user
|
||||
sensitive true
|
||||
variables redis_url: node["kosmos-mastodon"]["redis_url"],
|
||||
domain: node["kosmos-mastodon"]["domain"],
|
||||
alternate_domains: node["kosmos-mastodon"]["alternate_domains"],
|
||||
active_record_encryption_deterministic_key: credentials["active_record_encryption_deterministic_key"],
|
||||
active_record_encryption_key_derivation_salt: credentials["active_record_encryption_key_derivation_salt"],
|
||||
active_record_encryption_primary_key: credentials["active_record_encryption_primary_key"],
|
||||
paperclip_secret: credentials['paperclip_secret'],
|
||||
secret_key_base: credentials['secret_key_base'],
|
||||
otp_secret: credentials['otp_secret'],
|
||||
ldap: ldap_config,
|
||||
smtp_login: credentials['smtp_user_name'],
|
||||
smtp_password: credentials['smtp_password'],
|
||||
smtp_from_address: "mail@#{node['kosmos-mastodon']['domain']}",
|
||||
s3_endpoint: node["kosmos-mastodon"]["s3_endpoint"],
|
||||
s3_region: node["kosmos-mastodon"]["s3_region"],
|
||||
s3_bucket: node["kosmos-mastodon"]["s3_bucket"],
|
||||
s3_alias_host: node["kosmos-mastodon"]["s3_alias_host"],
|
||||
aws_access_key_id: credentials['s3_key_id'],
|
||||
aws_secret_access_key: credentials['s3_secret_key'],
|
||||
vapid_private_key: credentials['vapid_private_key'],
|
||||
vapid_public_key: credentials['vapid_public_key'],
|
||||
db_pass: postgresql_credentials['mastodon_user_password'],
|
||||
db_host: "pg.kosmos.local",
|
||||
sso_account_sign_up_url: node["kosmos-mastodon"]["sso_account_sign_up_url"],
|
||||
sso_account_reset_password_url: node["kosmos-mastodon"]["sso_account_reset_password_url"],
|
||||
sso_account_resend_confirmation_url: node["kosmos-mastodon"]["sso_account_resend_confirmation_url"],
|
||||
default_locale: node["kosmos-mastodon"]["default_locale"],
|
||||
allowed_private_addresses: node["kosmos-mastodon"]["allowed_private_addresses"],
|
||||
libre_translate_endpoint: node["kosmos-mastodon"]["libre_translate_endpoint"]
|
||||
notifies :run, "execute[restart mastodon services]", :delayed
|
||||
end
|
||||
|
||||
execute "bundle install" do
|
||||
environment deploy_env
|
||||
user mastodon_user
|
||||
cwd mastodon_path
|
||||
command "bundle install --without development,test --deployment"
|
||||
end
|
||||
|
||||
execute "yarn install" do
|
||||
environment deploy_env
|
||||
user mastodon_user
|
||||
cwd mastodon_path
|
||||
command "corepack prepare && yarn install --immutable"
|
||||
end
|
||||
|
||||
execute "rake assets:precompile" do
|
||||
environment deploy_env
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
cwd mastodon_path
|
||||
command "bundle exec rake assets:precompile"
|
||||
end
|
||||
|
||||
execute "rake db:migrate" do
|
||||
environment deploy_env
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
cwd mastodon_path
|
||||
command "bundle exec rake db:migrate"
|
||||
end
|
||||
|
||||
service "mastodon-web" do
|
||||
action [:enable, :start]
|
||||
end
|
||||
|
||||
service "mastodon-sidekiq" do
|
||||
action [:enable, :start]
|
||||
end
|
||||
|
||||
service "mastodon-sidekiq-scheduler" do
|
||||
action [:enable, :start]
|
||||
end
|
||||
|
||||
service "mastodon-streaming" do
|
||||
action [:enable, :start]
|
||||
end
|
||||
|
||||
#
|
||||
# Delete cached remote media older than 30 days
|
||||
# Will be re-fetched if necessary
|
||||
#
|
||||
|
||||
systemd_unit 'mastodon-delete-old-media-cache.service' do
|
||||
content({
|
||||
Unit: {
|
||||
Description: 'Delete old Mastodon media cache'
|
||||
},
|
||||
Service: {
|
||||
Type: "oneshot",
|
||||
WorkingDirectory: mastodon_path,
|
||||
Environment: "RAILS_ENV=#{rails_env}",
|
||||
ExecStart: "#{bundle_path} exec bin/tootctl media remove --days 30",
|
||||
}
|
||||
})
|
||||
triggers_reload true
|
||||
action [:create]
|
||||
end
|
||||
|
||||
systemd_unit 'mastodon-delete-old-media-cache.timer' do
|
||||
content({
|
||||
Unit: {
|
||||
Description: 'Delete old Mastodon media cache'
|
||||
},
|
||||
Timer: {
|
||||
OnCalendar: '*-*-* 00:00:00',
|
||||
Persistent: 'true'
|
||||
},
|
||||
Install: {
|
||||
WantedBy: 'timer.target'
|
||||
}
|
||||
})
|
||||
triggers_reload true
|
||||
action [:create, :enable, :start]
|
||||
end
|
||||
|
||||
firewall_rule "mastodon_app" do
|
||||
port node['kosmos-mastodon']['app_port']
|
||||
source "10.1.1.0/24"
|
||||
protocol :tcp
|
||||
command :allow
|
||||
end
|
||||
|
||||
firewall_rule 'mastodon_streaming' do
|
||||
port node['kosmos-mastodon']['streaming_port']
|
||||
source "10.1.1.0/24"
|
||||
protocol :tcp
|
||||
command :allow
|
||||
end
|
||||
# Run migrations and manage the services.
|
||||
include_recipe "kosmos-mastodon::deploy" if node["kosmos-mastodon"]["deploy"]
|
||||
@@ -0,0 +1,97 @@
|
||||
#
|
||||
# Cookbook Name:: kosmos-mastodon
|
||||
# Recipe:: dependencies
|
||||
#
|
||||
# Installs everything Mastodon needs to run, without deploying or starting the
|
||||
# application itself. Can be run ahead of a deployment to shorten downtime.
|
||||
#
|
||||
|
||||
node.override["kosmos_nodejs"]["version"] = node["kosmos-mastodon"]["nodejs_version"]
|
||||
|
||||
include_recipe "kosmos-nodejs"
|
||||
include_recipe "firewall"
|
||||
|
||||
elasticsearch_user 'elasticsearch'
|
||||
|
||||
# Elasticsearch 7.x ships a bundled JDK and no JAVA_HOME is configured, so no
|
||||
# system Java is needed (the java cookbook's openjdk recipe no longer supports
|
||||
# Ubuntu 24.04 anyway).
|
||||
elasticsearch_install 'elasticsearch' do
|
||||
type 'package'
|
||||
# The current version of the elasticsearch cookbook doesn't like versions
|
||||
# it doesn't know about. This would still be installing the default (7.17.9)
|
||||
# on a new machine, but it doesn't upgrade the package
|
||||
download_url 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.7-amd64.deb'
|
||||
# SHA256
|
||||
download_checksum '5c588d779023672ba4e315e7cd4db068ac60a38873a35973574a1cae858c2030'
|
||||
action :install
|
||||
end
|
||||
|
||||
elasticsearch_configure 'elasticsearch' do
|
||||
allocated_memory node["kosmos-mastodon"]["elasticsearch"]["allocated_memory"]
|
||||
|
||||
jvm_options %w(
|
||||
-XX:+AlwaysPreTouch
|
||||
-server
|
||||
-Xss1m
|
||||
-Djava.awt.headless=true
|
||||
-Dfile.encoding=UTF-8
|
||||
-Djna.nosys=true
|
||||
-XX:-OmitStackTraceInFastThrow
|
||||
-Dio.netty.noUnsafe=true
|
||||
-Dio.netty.noKeySetOptimization=true
|
||||
-Dio.netty.recycler.maxCapacityPerThread=0
|
||||
-XX:+HeapDumpOnOutOfMemoryError
|
||||
)
|
||||
end
|
||||
|
||||
elasticsearch_service 'elasticsearch'
|
||||
|
||||
mastodon_path = node["kosmos-mastodon"]["directory"]
|
||||
mastodon_user = "mastodon"
|
||||
mastodon_home = "/home/#{mastodon_user}"
|
||||
|
||||
group mastodon_user do
|
||||
gid 62786
|
||||
end
|
||||
|
||||
user mastodon_user do
|
||||
comment "mastodon user"
|
||||
uid 62786
|
||||
gid 62786
|
||||
shell "/bin/bash"
|
||||
home mastodon_home
|
||||
end
|
||||
|
||||
directory mastodon_home do
|
||||
owner mastodon_user
|
||||
group mastodon_user
|
||||
mode "0755"
|
||||
end
|
||||
|
||||
directory mastodon_path do
|
||||
owner mastodon_user
|
||||
group mastodon_user
|
||||
mode "0755"
|
||||
end
|
||||
|
||||
# Mastodon 4.6 dropped ImageMagick in favor of libvips and requires libvips >= 8.13
|
||||
package %w(build-essential ffmpeg libxml2-dev libxslt1-dev file git
|
||||
curl pkg-config libprotobuf-dev protobuf-compiler libidn-dev
|
||||
libjemalloc2 libpq-dev libvips-dev)
|
||||
|
||||
ruby_version = node["kosmos-mastodon"]["ruby_version"]
|
||||
|
||||
ruby_path = "/opt/ruby_build/builds/#{ruby_version}"
|
||||
|
||||
ruby_build_install node["kosmos-mastodon"]["ruby_build_version"]
|
||||
ruby_build_definition ruby_version do
|
||||
prefix_path ruby_path
|
||||
end
|
||||
|
||||
# Node 24 ships corepack >= 0.30, for which `corepack prepare` without an
|
||||
# argument is no longer valid. Enable the shims as root and let yarn pick up
|
||||
# the version pinned in package.json instead.
|
||||
execute "corepack enable" do
|
||||
command "corepack enable"
|
||||
end
|
||||
@@ -0,0 +1,240 @@
|
||||
#
|
||||
# Cookbook Name:: kosmos-mastodon
|
||||
# Recipe:: deploy
|
||||
#
|
||||
# Runs database migrations and manages the services. Requires the application
|
||||
# to have been checked out and built by kosmos-mastodon::build. Migrations and
|
||||
# the service restart run once per checked-out revision.
|
||||
#
|
||||
|
||||
mastodon_path = node["kosmos-mastodon"]["directory"]
|
||||
mastodon_user = "mastodon"
|
||||
|
||||
bind_ip = if node.chef_environment == "production"
|
||||
node["knife_zero"]["host"]
|
||||
else
|
||||
node["kosmos-mastodon"]["bind_ip"]
|
||||
end
|
||||
|
||||
ruby_version = node["kosmos-mastodon"]["ruby_version"]
|
||||
ruby_path = "/opt/ruby_build/builds/#{ruby_version}"
|
||||
bundle_path = "#{ruby_path}/bin/bundle"
|
||||
|
||||
rails_env = node.chef_environment == "development" ? "development" : "production"
|
||||
deploy_env = {
|
||||
# FIXME: /usr/bin was missing from PATH when running `yarn install`
|
||||
"PATH" => "#{ruby_path}/bin:/usr/bin:$PATH",
|
||||
"HOME" => "/home/#{mastodon_user}",
|
||||
"RAILS_ENV" => rails_env,
|
||||
"NODE_ENV" => rails_env,
|
||||
"COREPACK_ENABLE_DOWNLOAD_PROMPT" => "0"
|
||||
}
|
||||
|
||||
# Run migrations, restart services and (re)build the search index once per
|
||||
# checked-out revision, regardless of whether the code was pre-built.
|
||||
deploy_uptodate = "test -f #{mastodon_path}/tmp/deployed-revision && " \
|
||||
"test \"$(cat #{mastodon_path}/tmp/deployed-revision)\" = \"$(git -C #{mastodon_path} rev-parse HEAD)\""
|
||||
|
||||
execute "systemctl daemon-reload" do
|
||||
command "systemctl daemon-reload"
|
||||
action :nothing
|
||||
end
|
||||
|
||||
# mastodon-web service
|
||||
#
|
||||
template "/lib/systemd/system/mastodon-web.service" do
|
||||
source "mastodon-web.systemd.service.erb"
|
||||
variables user: mastodon_user,
|
||||
app_dir: mastodon_path,
|
||||
bind: bind_ip,
|
||||
port: node["kosmos-mastodon"]["app_port"],
|
||||
bundle_path: bundle_path
|
||||
notifies :run, "execute[systemctl daemon-reload]", :immediately
|
||||
notifies :restart, "service[mastodon-web]", :delayed
|
||||
end
|
||||
|
||||
# mastodon-sidekiq service
|
||||
#
|
||||
template "/lib/systemd/system/mastodon-sidekiq.service" do
|
||||
source "mastodon-sidekiq.systemd.service.erb"
|
||||
variables user: mastodon_user,
|
||||
app_dir: mastodon_path,
|
||||
bundle_path: bundle_path,
|
||||
sidekiq_threads: node["kosmos-mastodon"]["sidekiq_threads"]
|
||||
notifies :run, "execute[systemctl daemon-reload]", :immediately
|
||||
notifies :restart, "service[mastodon-sidekiq]", :delayed
|
||||
end
|
||||
|
||||
# mastodon-sidekiq-scheduler service
|
||||
#
|
||||
template "/lib/systemd/system/mastodon-sidekiq-scheduler.service" do
|
||||
source "mastodon-sidekiq-scheduler.systemd.service.erb"
|
||||
variables user: mastodon_user,
|
||||
app_dir: mastodon_path,
|
||||
bundle_path: bundle_path,
|
||||
sidekiq_threads: 1
|
||||
notifies :run, "execute[systemctl daemon-reload]", :immediately
|
||||
notifies :restart, "service[mastodon-sidekiq-scheduler]", :delayed
|
||||
end
|
||||
|
||||
# mastodon-streaming service
|
||||
#
|
||||
template "/lib/systemd/system/mastodon-streaming.service" do
|
||||
source "mastodon-streaming.systemd.service.erb"
|
||||
variables user: mastodon_user,
|
||||
app_dir: mastodon_path,
|
||||
bind: bind_ip,
|
||||
port: node["kosmos-mastodon"]["streaming_port"]
|
||||
notifies :run, "execute[systemctl daemon-reload]", :immediately
|
||||
notifies :restart, "service[mastodon-streaming]", :delayed
|
||||
end
|
||||
|
||||
execute "restart mastodon services" do
|
||||
command "systemctl restart mastodon-web mastodon-sidekiq mastodon-sidekiq-scheduler mastodon-streaming"
|
||||
action :nothing
|
||||
end
|
||||
|
||||
# Populate the Elasticsearch indices in the background. The indices and
|
||||
# mappings are created synchronously during the deployment; this unit only does
|
||||
# the (potentially very long) import, so it is started without blocking. Declared
|
||||
# before the migration chain below because that chain starts it.
|
||||
systemd_unit 'mastodon-search-deploy.service' do
|
||||
content({
|
||||
Unit: {
|
||||
Description: 'Populate the Mastodon search index'
|
||||
},
|
||||
Service: {
|
||||
Type: "oneshot",
|
||||
User: mastodon_user,
|
||||
WorkingDirectory: mastodon_path,
|
||||
Environment: "RAILS_ENV=#{rails_env}",
|
||||
ExecStart: "#{bundle_path} exec bin/tootctl search deploy",
|
||||
TimeoutStartSec: "21600",
|
||||
}
|
||||
})
|
||||
triggers_reload true
|
||||
action [:create]
|
||||
end
|
||||
|
||||
# Mastodon 4.4+ splits migrations into pre- and post-deployment phases.
|
||||
# Pre-deployment migrations must run before the services are (re)started.
|
||||
execute "rake db:migrate (pre-deployment)" do
|
||||
environment deploy_env.merge("SKIP_POST_DEPLOYMENT_MIGRATIONS" => "true")
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
cwd mastodon_path
|
||||
command "bundle exec rake db:migrate"
|
||||
timeout 21_600
|
||||
not_if deploy_uptodate
|
||||
notifies :run, "execute[restart mastodon services]", :immediately
|
||||
notifies :run, "execute[rake db:migrate (post-deployment)]", :immediately
|
||||
end
|
||||
|
||||
execute "rake db:migrate (post-deployment)" do
|
||||
environment deploy_env
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
cwd mastodon_path
|
||||
command "bundle exec rake db:migrate"
|
||||
timeout 21_600
|
||||
action :nothing
|
||||
notifies :run, "execute[tootctl search deploy (create indices)]", :immediately
|
||||
end
|
||||
|
||||
# Create or upgrade the Elasticsearch indices and mappings without importing
|
||||
# data, so that search does not fail on a missing index. The (potentially very
|
||||
# long) import is deferred to a systemd unit started in the background below.
|
||||
execute "tootctl search deploy (create indices)" do
|
||||
environment deploy_env
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
cwd mastodon_path
|
||||
command "#{bundle_path} exec bin/tootctl search deploy --no-import"
|
||||
timeout 3_600
|
||||
action :nothing
|
||||
notifies :run, "execute[start mastodon search deploy]", :immediately
|
||||
notifies :run, "execute[record deployed revision]", :immediately
|
||||
end
|
||||
|
||||
execute "start mastodon search deploy" do
|
||||
command "systemctl start --no-block mastodon-search-deploy.service"
|
||||
action :nothing
|
||||
end
|
||||
|
||||
# Record the deployed revision. Runs as the mastodon user so git accepts the
|
||||
# repo (a root-run `git` would refuse due to dubious ownership).
|
||||
execute "record deployed revision" do
|
||||
user mastodon_user
|
||||
group mastodon_user
|
||||
cwd mastodon_path
|
||||
command "git rev-parse HEAD > tmp/deployed-revision"
|
||||
action :nothing
|
||||
end
|
||||
|
||||
service "mastodon-web" do
|
||||
action [:enable, :start]
|
||||
end
|
||||
|
||||
service "mastodon-sidekiq" do
|
||||
action [:enable, :start]
|
||||
end
|
||||
|
||||
service "mastodon-sidekiq-scheduler" do
|
||||
action [:enable, :start]
|
||||
end
|
||||
|
||||
service "mastodon-streaming" do
|
||||
action [:enable, :start]
|
||||
end
|
||||
|
||||
#
|
||||
# Delete cached remote media older than 30 days
|
||||
# Will be re-fetched if necessary
|
||||
#
|
||||
|
||||
systemd_unit 'mastodon-delete-old-media-cache.service' do
|
||||
content({
|
||||
Unit: {
|
||||
Description: 'Delete old Mastodon media cache'
|
||||
},
|
||||
Service: {
|
||||
Type: "oneshot",
|
||||
WorkingDirectory: mastodon_path,
|
||||
Environment: "RAILS_ENV=#{rails_env}",
|
||||
ExecStart: "#{bundle_path} exec bin/tootctl media remove --days 30",
|
||||
}
|
||||
})
|
||||
triggers_reload true
|
||||
action [:create]
|
||||
end
|
||||
|
||||
systemd_unit 'mastodon-delete-old-media-cache.timer' do
|
||||
content({
|
||||
Unit: {
|
||||
Description: 'Delete old Mastodon media cache'
|
||||
},
|
||||
Timer: {
|
||||
OnCalendar: '*-*-* 00:00:00',
|
||||
Persistent: 'true'
|
||||
},
|
||||
Install: {
|
||||
WantedBy: 'timer.target'
|
||||
}
|
||||
})
|
||||
triggers_reload true
|
||||
action [:create, :enable, :start]
|
||||
end
|
||||
|
||||
firewall_rule "mastodon_app" do
|
||||
port node['kosmos-mastodon']['app_port']
|
||||
source "10.1.1.0/24"
|
||||
protocol :tcp
|
||||
command :allow
|
||||
end
|
||||
|
||||
firewall_rule 'mastodon_streaming' do
|
||||
port node['kosmos-mastodon']['streaming_port']
|
||||
source "10.1.1.0/24"
|
||||
protocol :tcp
|
||||
command :allow
|
||||
end
|
||||
@@ -5,9 +5,10 @@
|
||||
|
||||
build_essential
|
||||
|
||||
version = "1.3.8"
|
||||
version = "1.9.6"
|
||||
venv = "/opt/libretranslate/venv"
|
||||
|
||||
%w{ python3 python3-pip python3-setuptools python3-dev }.each do |pkg|
|
||||
%w{ python3 python3-pip python3-setuptools python3-dev python3-venv }.each do |pkg|
|
||||
apt_package pkg
|
||||
end
|
||||
|
||||
@@ -17,19 +18,26 @@ user "libretranslate" do
|
||||
manage_home true
|
||||
end
|
||||
|
||||
# LibreTranslate is installed into a dedicated virtualenv. Ubuntu 24.04's
|
||||
# system Python is externally managed (PEP 668) and refuses `pip install`.
|
||||
bash "create_libretranslate_venv" do
|
||||
code "sudo -u libretranslate python3 -m venv #{venv}"
|
||||
not_if { ::File.exist?("#{venv}/bin/pip") }
|
||||
end
|
||||
|
||||
bash "install_libretranslate" do
|
||||
code "sudo -u libretranslate pip3 install --user --prefer-binary libretranslate==#{version}"
|
||||
code "sudo -u libretranslate #{venv}/bin/pip install --prefer-binary libretranslate==#{version}"
|
||||
action :run
|
||||
not_if { `sudo -u libretranslate pip3 list |grep libretranslate`.split(' ')[1] == version rescue false }
|
||||
not_if "#{venv}/bin/pip show libretranslate 2>/dev/null | grep -q 'Version: #{version}'"
|
||||
notifies :restart, "service[libretranslate]", :delayed
|
||||
end
|
||||
|
||||
languages = `sudo -u libretranslate /opt/libretranslate/.local/bin/argospm search`
|
||||
languages = `sudo -u libretranslate #{venv}/bin/argospm search`
|
||||
languages.each_line do |line|
|
||||
lang = line.split(':').first
|
||||
|
||||
bash "install_lt_#{lang}" do
|
||||
code "sudo -u libretranslate /opt/libretranslate/.local/bin/argospm install #{lang}"
|
||||
code "sudo -u libretranslate #{venv}/bin/argospm install #{lang}"
|
||||
action :nothing
|
||||
end
|
||||
end
|
||||
@@ -46,7 +54,7 @@ systemd_unit "libretranslate.service" do
|
||||
User: "libretranslate",
|
||||
Group: "libretranslate",
|
||||
WorkingDirectory: "/opt/libretranslate/",
|
||||
ExecStart: "/opt/libretranslate/.local/bin/libretranslate --host 127.0.0.1 --port 5000 --disable-files-translation",
|
||||
ExecStart: "#{venv}/bin/libretranslate --host 127.0.0.1 --port 5000 --disable-files-translation",
|
||||
Restart: "always"
|
||||
},
|
||||
Install: {
|
||||
|
||||
@@ -17,7 +17,6 @@ ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=<%= @active_record_encryption_key_d
|
||||
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=<%= @active_record_encryption_primary_key %>
|
||||
PAPERCLIP_SECRET=<%= @paperclip_secret %>
|
||||
SECRET_KEY_BASE=<%= @secret_key_base %>
|
||||
OTP_SECRET=<%= @otp_secret %>
|
||||
|
||||
# Registrations
|
||||
# Single user mode will disable registrations and redirect frontpage to the first profile
|
||||
@@ -74,6 +73,10 @@ AWS_SECRET_ACCESS_KEY=<%= @aws_secret_access_key %>
|
||||
|
||||
# locale
|
||||
DEFAULT_LOCALE=<%= @default_locale %>
|
||||
FORCE_DEFAULT_LOCALE=<%= @force_default_locale %>
|
||||
|
||||
# Email subscriptions (Mastodon 4.6+)
|
||||
DISABLE_EMAIL_SUBSCRIPTIONS=<%= @disable_email_subscriptions %>
|
||||
|
||||
<% if @libre_translate_endpoint %>
|
||||
# translate
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
[Unit]
|
||||
Description=mastodon-sidekiq-scheduler
|
||||
Requires=redis@6379.service
|
||||
After=redis@6379.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
+1
-3
@@ -1,7 +1,5 @@
|
||||
[Unit]
|
||||
Description=mastodon-sidekiq
|
||||
Requires=redis@6379.service
|
||||
After=redis@6379.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
@@ -11,7 +9,7 @@ Environment="RAILS_ENV=production"
|
||||
Environment="DB_POOL=<%= @sidekiq_threads %>"
|
||||
Environment="MALLOC_ARENA_MAX=2"
|
||||
Environment="LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
|
||||
ExecStart=<%= @bundle_path %> exec sidekiq -c <%= @sidekiq_threads %> -q default -q mailers -q pull -q push -q ingress
|
||||
ExecStart=<%= @bundle_path %> exec sidekiq -c <%= @sidekiq_threads %> -q default -q mailers -q pull -q push -q ingress -q fasp
|
||||
TimeoutSec=15
|
||||
Restart=always
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
[Unit]
|
||||
Description=mastodon-web
|
||||
Requires=redis@6379.service
|
||||
After=redis@6379.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
@@ -58,7 +58,9 @@ end
|
||||
execute "bundle install" do
|
||||
user deploy_user
|
||||
cwd deploy_path
|
||||
command "#{bundle_path} install --without development,test --deployment"
|
||||
command "#{bundle_path} config set --local deployment true && " \
|
||||
"#{bundle_path} config set --local without 'development test' && " \
|
||||
"#{bundle_path} install"
|
||||
end
|
||||
|
||||
template "#{deploy_path}/config.yml.erb" do
|
||||
|
||||
Reference in new issue
Block a user