{"id":166,"date":"2022-11-21T07:22:17","date_gmt":"2022-11-21T12:22:17","guid":{"rendered":"https:\/\/daveking.com\/blog\/?p=166"},"modified":"2022-11-21T11:59:24","modified_gmt":"2022-11-21T16:59:24","slug":"things-they-dont-tell-you-about-installing-a-mastodon-server","status":"publish","type":"post","link":"https:\/\/daveking.com\/blog\/index.php\/2022\/11\/21\/things-they-dont-tell-you-about-installing-a-mastodon-server\/","title":{"rendered":"Things They Don&#8217;t Tell You About Installing A Mastodon Server"},"content":{"rendered":"\n<p>I followed <a href=\"https:\/\/docs.joinmastodon.org\/user\/run-your-own\/\">the directions in the Mastodon documentation<\/a> for setting up a Mastodon server.  Along the way, I discovered several stoppers that I had to figure out for myself.  I&#8217;m writing these things down so I don&#8217;t forget how I addressed them.  <\/p>\n\n\n\n<p>I did the install on an Ubuntu 22.04.1 (Jammy) Linux server.  (I used my <a href=\"https:\/\/daveking.com\/blog\/index.php\/2022\/11\/15\/free-internet-servers\/\">&#8220;Always Free&#8221; server from Oracle<\/a>.)  I opted for the <a href=\"https:\/\/docs.joinmastodon.org\/admin\/install\/\">Installing From Source<\/a> option. Some of the issues I encountered likely relate to that installation option, others may be more universal.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Grant Web Server Permission To Mastodon&#8217;s Files<\/h3>\n\n\n\n<p>The first time I tried to access the site after completing the instructions, I got error code messages back from the web server.  The nginx error log showed permission was being denied when it tried to access the files in the \/home\/mastodon\/live\/public directory.  I resolved this by adding the www-data userid which runs nginx to the mastodon user group on the server.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Precompile The Mastodon Assets<\/h3>\n\n\n\n<p>When I tried accessing the site again I still got 500 error code messages from the web server.  The system log contained errors from the mastodon-web service saying that files were missing: &#8220;Webpacker can&#8217;t find media\/images\/preview.png &#8230;&#8221;  I needed to run the asset precompile task to create the missing file packages.  The <a href=\"https:\/\/docs.joinmastodon.org\/admin\/troubleshooting\/#after-an-upgrade-to-a-newer-version-some-pages-look-weird-like-they-have-unstyled-elements-why\">troubleshooting notes<\/a> mentioned this as something that needs to be done after upgrading the Mastodon code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo su mastodon -\n$ cd ~\/live\n$ <span style=\"background-color: initial; font-family: inherit; font-size: inherit;\">RAILS_ENV=production bin\/rails assets:precompile<\/span><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Grant Public Access To The Object Store<\/h3>\n\n\n\n<p>When I set up my AWS S3 object store I discovered that I needed to <a href=\"https:\/\/docs.aws.amazon.com\/AmazonS3\/latest\/userguide\/configuring-block-public-access-bucket.html\">enable public access<\/a> to the S3 bucket that the mastodon server created.  It would have perhaps been better if I had created the S3 bucket I was going to use before <a href=\"https:\/\/docs.joinmastodon.org\/admin\/install\/#generating-a-configuration\">running the Mastodon server configuration wizard<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">AWS Link In NGINX Configuration For The Object Store Proxy<\/h3>\n\n\n\n<p>The configuration for nginx that is suggested in <a href=\"https:\/\/docs.joinmastodon.org\/admin\/optional\/object-storage-proxy\/\">the instructions<\/a> includes this line defining the base URL for the files in the object store:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"nginx\" class=\"language-nginx\">set <em>$s3_backend<\/em> 'https:\/\/YOUR_BUCKET_NAME.YOUR_S3_HOSTNAME';<\/code><\/pre>\n\n\n\n<p>The AWS S3 link should instead be in this format:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"nginx\" class=\"language-nginx\">set <em>$s3_backend<\/em> 'https:\/\/s3.amazon.com\/YOUR_BUCKET_NAME';<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Establish A Secure Tunnel Between The Mastodon Server And The ElasticSearch Server<\/h3>\n\n\n\n<p>The <a href=\"https:\/\/docs.joinmastodon.org\/admin\/optional\/elasticsearch\/#install\">installation instructions<\/a> mention the fact that ElasticSearch, by default, provides no security layer to control access.  To maintain a secure environment, ES should only be used by local processes or, if it must be accessed remotely, some sort of secure network connection should be used.  I already had an ES server for another system that I run and I didn&#8217;t want to create another one just for Mastodon.<\/p>\n\n\n\n<p>I used SSH secure tunneling to provide a secure connection between the mastodon server and the existing ES server.  I use the <code>autossh<\/code> application on the mastodon server to set the tunnel up at system boot and to keep it running.  The following two files define a systemd service for this purpose.  SSH login between the two systems should be set up and tested before starting this service.  Once the tunnel is in place the mastodon server can be configured to access ES at <code>localhost:9200<\/code> and communications between it and the ES server will be secure and encrypted.<\/p>\n\n\n\n<p>\/etc\/systemd\/system\/elasticsearch-tunnel.service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">[Unit]\nDescription=SSH tunnel to the elasticsearch server\nWants=network-online.target\nAfter=network-online.target sshd.service\n\n[Service]\nType=simple\nRestart=on-failure\nEnvironmentFile=\/etc\/default\/elasticsearch-tunnel\nExecStart=\/usr\/bin\/autossh -M 20000 -4 -L ${ES_PORT}:${PRIVATE_IP}:${ES_PORT} -N ${USER}@${PUBLIC_IP}\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n\n\n\n<p>\/etc\/default\/elasticsearch-tunnel:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">#  This file contains the values required by the elasticsearch-tunnel systemd service.\n#\n#  This file should be located at \/etc\/default\/elasticsearch-tunnel.\n\n#  The publicly accessable IP address for the elasticsearch server\nPUBLIC_IP=\n\n#  The private network IP address where the elasticsearch server listens for connections\nPRIVATE_IP=127.0.0.1\n\n#  The userid on the elasticsearch server that will be used for the SSH login\nUSER=\n\n#  The port on the elasticsearch private network IP address where the server listens for connections\nES_PORT=9200<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Notes on how I resolved the stoppers that I encountered while installing my own Mastodon server.<\/p>\n","protected":false},"author":1,"featured_media":168,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[22,13],"tags":[23,25,12],"class_list":["post-166","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-howto","category-software-that-i-use","tag-howto","tag-mastodon","tag-software","eq-blocks"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/daveking.com\/blog\/wp-content\/uploads\/2022\/11\/mastodon-sculpture.jpg?fit=500%2C263&ssl=1","jetpack-related-posts":[],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=166"}],"version-history":[{"count":10,"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/166\/revisions"}],"predecessor-version":[{"id":179,"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/166\/revisions\/179"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/media\/168"}],"wp:attachment":[{"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daveking.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}