<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>RaspberryPi &amp;mdash; roblog</title>
    <link>https://blog.rstokes.uk/tag:RaspberryPi</link>
    <description>Random musings—mostly for me, but you might accidentally find something useful too</description>
    <pubDate>Thu, 23 Jul 2026 12:10:46 +0100</pubDate>
    <item>
      <title>Installing Pixelfed Glitch on a Raspberry Pi</title>
      <link>https://blog.rstokes.uk/installing-pixelfed-glitch-on-a-raspberry-pi</link>
      <description>&lt;![CDATA[Although the official Pixelfed Glitch Docker docs are fairly short, I found a few rough edges when installing it on a Raspberry Pi. This guide pulls the official instructions together with the fixes I needed along the way.&#xA;&#xA;This uses the Docker version of Pixelfed Glitch, with MariaDB and Redis running as Docker containers.&#xA;&#xA;!--more--&#xA;&#xA;div style=&#34;margin-top:-20px&#34;/div&#xA;&#xA;Contents&#xA;&#xA;a href=&#34;#install-docker&#34;Step 1 – Install Docker/a&#xA;a href=&#34;#allow-your-user-to-run-docker&#34;Step 2 – Allow your user to run Docker/a&#xA;a href=&#34;#create-the-pixelfed-glitch-directory&#34;Step 3 – Create the Pixelfed Glitch directory/a&#xA;a href=&#34;#download-the-docker-files&#34;Step 4 – Download the Docker files/a&#xA;a href=&#34;#edit-the-environment-file&#34;Step 5 – Edit the environment file/a&#xA;a href=&#34;#prepare-pixelfeds-storage-directories&#34;Step 6 – Prepare Pixelfed&#39;s storage directories/a&#xA;a href=&#34;#start-pixelfed-glitch&#34;Step 7 – Start Pixelfed Glitch/a&#xA;a href=&#34;#generate-the-application-and-oauth-keys&#34;Step 8 – Generate the application and OAuth keys/a&#xA;a href=&#34;#stop-first-time-setup-from-running-again&#34;Step 9 – Stop first-time setup from running again/a&#xA;a href=&#34;#check-the-site&#34;Step 10 – Check the site/a&#xA;a href=&#34;#create-the-first-user&#34;Step 11 – Create the first user/a&#xA;a href=&#34;#create-another-user&#34;Step 12 – Create another user/a&#xA;a href=&#34;#useful-checks&#34;Step 13 – Useful checks/a&#xA;a href=&#34;#mobile-app-login-and-2fa&#34;Step 14 – Mobile app login and 2FA/a&#xA;a href=&#34;#reboot-behaviour&#34;Step 15 – Reboot behaviour/a&#xA;a href=&#34;#backups&#34;Step 16 – Backups/a&#xA;a href=&#34;#troubleshooting-notes&#34;Troubleshooting notes/a&#xA;&#xA;div id=&#34;install-docker&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 1. Install Docker&#xA;&#xA;Pixelfed Glitch will run inside Docker containers. This means we do not need to manually install PHP, MariaDB, Redis, Node, Composer, or most of the other application dependencies on the Raspberry Pi itself.&#xA;&#xA;i. Update the package list:&#xA;&#xA;presudo apt update &amp;&amp; sudo apt upgrade/pre&#xA;&#xA;ii. Install the packages needed to add Docker&#39;s repository:&#xA;&#xA;presudo apt install -y ca-certificates curl/pre&#xA;&#xA;iii. Create the keyrings directory:&#xA;&#xA;presudo install -m 0755 -d /etc/apt/keyrings/pre&#xA;&#xA;iv. Download Docker&#39;s GPG key:&#xA;&#xA;presudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc/pre&#xA;&#xA;v. Make the key readable:&#xA;&#xA;presudo chmod a+r /etc/apt/keyrings/docker.asc/pre&#xA;&#xA;vi. Add Docker&#39;s repository:&#xA;&#xA;presudo tee /etc/apt/sources.list.d/docker.sources &amp;lt;&amp;lt;EOF&#xA;Types: deb&#xA;URIs: https://download.docker.com/linux/debian&#xA;Suites: $(. /etc/os-release &amp;&amp; echo &#34;$VERSIONCODENAME&#34;)&#xA;Components: stable&#xA;Architectures: $(dpkg --print-architecture)&#xA;Signed-By: /etc/apt/keyrings/docker.asc&#xA;EOF/pre&#xA;&#xA;vii. Update the package list again:&#xA;&#xA;presudo apt update/pre&#xA;&#xA;viii. Install Docker and the Compose plugin:&#xA;&#xA;presudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin/pre&#xA;&#xA;ix. Check Docker is running:&#xA;&#xA;presudo systemctl status docker/pre&#xA;&#xA;x. Enable Docker to start at boot:&#xA;&#xA;presudo systemctl enable docker.service&#xA;sudo systemctl enable containerd.service/pre&#xA;&#xA;div id=&#34;allow-your-user-to-run-docker&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 2. Allow your user to run Docker&#xA;&#xA;By default, Docker commands need sudo. To run docker compose as your normal user, add your user to the docker group.&#xA;&#xA;i. Create the group, if it does not already exist:&#xA;&#xA;presudo groupadd docker 2  /dev/null || true/pre&#xA;&#xA;ii. Add your user to it:&#xA;&#xA;presudo usermod -aG docker $USER/pre&#xA;&#xA;iii. Log out of SSH and log back in, or reboot the Pi.&#xA;&#xA;iv. Test Docker without sudo:&#xA;&#xA;predocker run hello-world/pre&#xA;&#xA;If this works, Docker is ready.&#xA;&#xA;div id=&#34;create-the-pixelfed-glitch-directory&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 3. Create the Pixelfed Glitch directory&#xA;&#xA;I installed Pixelfed Glitch under my home directory:&#xA;&#xA;precd /home/pi&#xA;mkdir -p pixelfed-glitch&#xA;cd pixelfed-glitch/pre&#xA;&#xA;Change /home/pi to match your own username if needed.&#xA;&#xA;div id=&#34;download-the-docker-files&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 4. Download the Docker files&#xA;&#xA;Download the Docker Compose file and the example environment file from the Pixelfed Glitch repository:&#xA;&#xA;precurl -fsSL https://raw.githubusercontent.com/pixelfed-glitch/pixelfed/develop/docker-compose.yml -o docker-compose.yml&#xA;curl -fsSL https://raw.githubusercontent.com/pixelfed-glitch/pixelfed/develop/.env.docker -o .env/pre&#xA;&#xA;The docker-compose.yml file defines the containers. The .env file holds site-specific settings such as the domain name, database password, upload limits, email settings, and Docker image tags.&#xA;&#xA;div id=&#34;edit-the-environment-file&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 5. Edit the environment file&#xA;&#xA;Open the .env file:&#xA;&#xA;prenano .env/pre&#xA;&#xA;At minimum, change the following values.&#xA;&#xA;Set the name of the site:&#xA;&#xA;preAPPNAME=&#34;My Pixelfed Site&#34;/pre&#xA;&#xA;Set the domain name, without https:// and without a trailing slash:&#xA;&#xA;preAPPDOMAIN=&#34;photos.example.com&#34;/pre&#xA;&#xA;Leave APPURL like this:&#xA;&#xA;preAPPURL=&#34;https://${APPDOMAIN}&#34;/pre&#xA;&#xA;Leave ADMINDOMAIN like this:&#xA;&#xA;preADMINDOMAIN=&#34;${APPDOMAIN}&#34;/pre&#xA;&#xA;Set a public contact email address:&#xA;&#xA;preINSTANCECONTACTEMAIL=&#34;admin@example.com&#34;/pre&#xA;&#xA;Set a secure database password:&#xA;&#xA;preDBPASSWORD=&#34;CHANGETHISTOALONGRANDOMPASSWORD&#34;/pre&#xA;&#xA;If you do not plan to send email at first, you can disable mandatory email verification:&#xA;&#xA;preENFORCEEMAILVERIFICATION=&#34;false&#34;/pre&#xA;&#xA;Make sure OAuth is enabled, as this is needed for Pixelfed mobile apps:&#xA;&#xA;preOAUTHENABLED=&#34;true&#34;/pre&#xA;&#xA;Leave APPKEY empty at this stage:&#xA;&#xA;preAPPKEY=/pre&#xA;&#xA;Pixelfed will generate this later. If you ever set it manually, it must be one single Laravel key, for example:&#xA;&#xA;preAPPKEY=base64:CHANGETHISTOONEVALIDKEYONLY/pre&#xA;&#xA;Do not paste two keys together on the same line.&#xA;&#xA;div id=&#34;prepare-pixelfeds-storage-directories&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 6. Prepare Pixelfed&#39;s storage directories&#xA;&#xA;The Docker image expects several Laravel storage paths to exist. Creating them now avoids a startup error such as:&#xA;&#xA;prePlease provide a valid cache path./pre&#xA;&#xA;Run:&#xA;&#xA;precd /home/pi/pixelfed-glitch&#xA;&#xA;sudo mkdir -p docker-compose-state/data/pixelfed/storage/app/public&#xA;sudo mkdir -p docker-compose-state/data/pixelfed/storage/framework/cache/data&#xA;sudo mkdir -p docker-compose-state/data/pixelfed/storage/framework/sessions&#xA;sudo mkdir -p docker-compose-state/data/pixelfed/storage/framework/testing&#xA;sudo mkdir -p docker-compose-state/data/pixelfed/storage/framework/views&#xA;sudo mkdir -p docker-compose-state/data/pixelfed/storage/logs&#xA;sudo mkdir -p docker-compose-state/data/pixelfed/storage/docker/lock&#xA;sudo mkdir -p docker-compose-state/data/pixelfed/cache&#xA;&#xA;sudo chown -R 33:33 docker-compose-state/data/pixelfed/storage&#xA;sudo chown -R 33:33 docker-compose-state/data/pixelfed/cache/pre&#xA;&#xA;User ID 33 is www-data, which is the user Pixelfed runs as inside the container.&#xA;&#xA;div id=&#34;start-pixelfed-glitch&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 7. Start Pixelfed Glitch&#xA;&#xA;Start the containers:&#xA;&#xA;predocker compose up -d/pre&#xA;&#xA;This downloads the Pixelfed Glitch, MariaDB, and Redis images, creates the containers, and starts the first-time setup.&#xA;&#xA;Check the containers:&#xA;&#xA;predocker compose ps/pre&#xA;&#xA;You should eventually see web, worker, cron, db, and redis as Up.&#xA;&#xA;To watch the logs:&#xA;&#xA;predocker compose logs --tail=100 --follow/pre&#xA;&#xA;If you only want the web container logs:&#xA;&#xA;predocker compose logs --tail=100 web/pre&#xA;&#xA;div id=&#34;generate-the-application-and-oauth-keys&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 8. Generate the application and OAuth keys&#xA;&#xA;If the site shows a 500 error and the logs mention either of these:&#xA;&#xA;preNo application encryption key has been specified.&#xA;Invalid key supplied/pre&#xA;&#xA;run the following commands:&#xA;&#xA;predocker compose exec web php artisan key:generate --force&#xA;docker compose exec -u www-data web php artisan passport:keys --force/pre&#xA;&#xA;Then clear and rebuild Pixelfed&#39;s cached config:&#xA;&#xA;predocker compose exec -u www-data web php artisan view:clear&#xA;docker compose exec -u www-data web php artisan config:clear&#xA;docker compose exec -u www-data web php artisan cache:clear&#xA;docker compose exec -u www-data web php artisan config:cache/pre&#xA;&#xA;Restart the Pixelfed containers:&#xA;&#xA;predocker compose restart web worker cron/pre&#xA;&#xA;div id=&#34;stop-first-time-setup-from-running-again&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 9. Stop first-time setup from running again&#xA;&#xA;After the first-time setup has completed and the keys have been created, edit .env again:&#xA;&#xA;prenano .env/pre&#xA;&#xA;Add this line:&#xA;&#xA;preDOCKERAPPRUNONETIMESETUPTASKS=&#34;0&#34;/pre&#xA;&#xA;This stops Pixelfed from trying to recreate encryption keys on every container start.&#xA;&#xA;If this is not set, the container may restart repeatedly with an error like:&#xA;&#xA;preEncryption keys already exist. Use the --force option to overwrite them./pre&#xA;&#xA;Restart the stack:&#xA;&#xA;predocker compose down&#xA;docker compose up -d/pre&#xA;&#xA;Do not use docker compose down -v, as that removes Docker volumes.&#xA;&#xA;div id=&#34;check-the-site&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 10. Check the site&#xA;&#xA;Open your Pixelfed URL in a browser:&#xA;&#xA;prehttps://photos.example.com/pre&#xA;&#xA;If you are using NGINX as a reverse proxy, make sure it points to the Docker web port. In the default Pixelfed Glitch Docker file this is:&#xA;&#xA;pre8080/pre&#xA;&#xA;So the proxy target is:&#xA;&#xA;prehttp://127.0.0.1:8080/pre&#xA;&#xA;Check the running containers:&#xA;&#xA;predocker compose ps/pre&#xA;&#xA;If you see a 502 error, the web container is probably not running yet, or it is restarting. Check:&#xA;&#xA;predocker compose logs --tail=200 web/pre&#xA;&#xA;div id=&#34;create-the-first-user&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 11. Create the first user&#xA;&#xA;Create the first account:&#xA;&#xA;predocker compose exec -u www-data web php artisan user:create/pre&#xA;&#xA;Follow the prompts.&#xA;&#xA;To make the user an admin:&#xA;&#xA;predocker compose exec -u www-data web php artisan user:admin USERNAME/pre&#xA;&#xA;To manually verify an email address:&#xA;&#xA;predocker compose exec -u www-data web php artisan user:verifyemail USERNAME/pre&#xA;&#xA;For example:&#xA;&#xA;predocker compose exec -u www-data web php artisan user:admin rob&#xA;docker compose exec -u www-data web php artisan user:verifyemail rob/pre&#xA;&#xA;div id=&#34;create-another-user&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 12. Create another user&#xA;&#xA;Run the same create command again:&#xA;&#xA;predocker compose exec -u www-data web php artisan user:create/pre&#xA;&#xA;Follow the prompts and enter the new username.&#xA;&#xA;For example:&#xA;&#xA;prebnw/pre&#xA;&#xA;Only run the admin command for accounts that should have admin rights.&#xA;&#xA;div id=&#34;useful-checks&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 13. Useful checks&#xA;&#xA;Check container status:&#xA;&#xA;predocker compose ps/pre&#xA;&#xA;Show recent logs:&#xA;&#xA;predocker compose logs --tail=200 web/pre&#xA;&#xA;Check the current Pixelfed config values:&#xA;&#xA;predocker compose exec -u www-data web php artisan tinker --execute=&#39;&#xA;echo &#34;app.url=&#34;.config(&#34;app.url&#34;).PHPEOL;&#xA;echo &#34;oauth=&#34;.(config(&#34;pixelfed.oauthenabled&#34;) ? &#34;true&#34; : &#34;false&#34;).PHPEOL;&#xA;echo &#34;session.domain=&#34;.config(&#34;session.domain&#34;).PHPEOL;&#xA;&#39;/pre&#xA;&#xA;Check the application key:&#xA;&#xA;pregrep &#39;^APPKEY=&#39; .env/pre&#xA;&#xA;A valid key should look like one single line:&#xA;&#xA;preAPPKEY=base64:LONGRANDOMSTRINGHERE/pre&#xA;&#xA;Check the OAuth key files:&#xA;&#xA;predocker compose exec -u www-data web ls -l storage/oauth-private.key storage/oauth-public.key/pre&#xA;&#xA;div id=&#34;mobile-app-login-and-2fa&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 14. Mobile app login and 2FA&#xA;&#xA;The web version worked fine for me with 2FA enabled.&#xA;&#xA;The mobile app login flow was different. With 2FA enabled, the official Pixelfed app and Impressia both opened a web login pop-up, accepted the username, password, and 2FA code, then stayed in the web version inside the pop-up instead of returning to the app.&#xA;&#xA;The workaround was:&#xA;&#xA;Keep 2FA enabled on the admin account.&#xA;Use a separate non-admin account for mobile app login.&#xA;Disable 2FA on that non-admin account before logging in to the apps.&#xA;&#xA;If the web interface will not disable 2FA and clicking the green &#34;Enabled&#34; button only adds # to the URL, disable it from the database.&#xA;&#xA;First check the 2FA column names:&#xA;&#xA;predocker compose exec -u www-data web php artisan tinker --execute=&#39;&#xA;printr(arrayvalues(arrayfilter(&#xA;&#x9;Schema::getColumnListing(&#34;users&#34;),&#xA;&#x9;fn($c) =  strcontains(strtolower($c), &#34;two&#34;) || strcontains(strtolower($c), &#34;2fa&#34;) || strcontains(strtolower($c), &#34;otp&#34;)&#xA;)));&#xA;&#39;/pre&#xA;&#xA;On my install the columns were:&#xA;&#xA;pre2faenabled&#xA;2fasecret&#xA;2fabackupcodes&#xA;2fasetupat/pre&#xA;&#xA;To disable 2FA for a user called bnw:&#xA;&#xA;predocker compose exec -u www-data web php artisan tinker --execute=&#39;&#xA;DB::table(&#34;users&#34;)-  where(&#34;username&#34;, &#34;bnw&#34;)-  update([&#xA;&#x9;&#34;2faenabled&#34; =  false,&#xA;&#x9;&#34;2fasecret&#34; =  null,&#xA;&#x9;&#34;2fabackupcodes&#34; =  null,&#xA;&#x9;&#34;2fasetupat&#34; =  null,&#xA;]);&#xA;echo &#34;2FA disabled for bnw\n&#34;;&#xA;&#39;/pre&#xA;&#xA;After that, app login worked.&#xA;&#xA;div id=&#34;reboot-behaviour&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 15. Reboot behaviour&#xA;&#xA;The docker-compose.yml file uses:&#xA;&#xA;prerestart: unless-stopped/pre&#xA;&#xA;This means the containers should come back up after a reboot, as long as Docker itself starts on boot.&#xA;&#xA;Check Docker is enabled:&#xA;&#xA;presystemctl is-enabled docker/pre&#xA;&#xA;If needed:&#xA;&#xA;presudo systemctl enable docker/pre&#xA;&#xA;After a reboot, check Pixelfed:&#xA;&#xA;precd /home/pi/pixelfed-glitch&#xA;docker compose ps/pre&#xA;&#xA;One thing to remember: if you run this command:&#xA;&#xA;predocker compose down/pre&#xA;&#xA;the containers are removed. Docker cannot restart removed containers at boot. To recreate and start them:&#xA;&#xA;precd /home/pi/pixelfed-glitch&#xA;docker compose up -d/pre&#xA;&#xA;div id=&#34;backups&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 16. Backups&#xA;&#xA;At minimum, back up the Pixelfed Glitch install directory:&#xA;&#xA;pre/home/pi/pixelfed-glitch/pre&#xA;&#xA;This contains:&#xA;&#xA;predocker-compose.yml&#xA;.env&#xA;docker-compose-state//pre&#xA;&#xA;The .env file contains secrets, including the database password and application key, so store backups securely.&#xA;&#xA;The docker-compose-state directory contains the MariaDB data, Redis data, Pixelfed storage, and cache folders. For a live database, a proper database dump is safer than only copying files while containers are running.&#xA;&#xA;A simple manual MariaDB dump can be created with:&#xA;&#xA;precd /home/pi/pixelfed-glitch&#xA;docker compose exec db mariadb-dump -u pixelfed -p pixelfedprod   pixelfeddbbackup.sql/pre&#xA;&#xA;You will be prompted for the database password from .env.&#xA;&#xA;div id=&#34;troubleshooting-notes&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Troubleshooting notes&#xA;&#xA;a href=&#34;#docker-permission-denied&#34;Docker permission denied/a&#xA;a href=&#34;#missing-cache-path&#34;Missing cache path/a&#xA;a href=&#34;#invalid-application-key&#34;Invalid application key/a&#xA;a href=&#34;#first-time-setup-keeps-running&#34;First-time setup keeps running/a&#xA;&#xA;div id=&#34;docker-permission-denied&#34; style=&#34;margin-top:-5px&#34;/div&#xA;&#xA;Docker permission denied&#xA;&#xA;If you see:&#xA;&#xA;prepermission denied while trying to connect to the docker API at unix:///var/run/docker.sock/pre&#xA;&#xA;your user is not in the docker group, or the current login session has not picked up the new group membership.&#xA;&#xA;Fix:&#xA;&#xA;presudo usermod -aG docker $USER/pre&#xA;&#xA;Then log out and back in.&#xA;&#xA;div id=&#34;missing-cache-path&#34; style=&#34;margin-top:-5px&#34;/div&#xA;&#xA;Missing cache path&#xA;&#xA;If the web container restarts and logs show:&#xA;&#xA;prePlease provide a valid cache path./pre&#xA;&#xA;create the Laravel storage and cache folders from Step 6.&#xA;&#xA;div id=&#34;invalid-application-key&#34; style=&#34;margin-top:-5px&#34;/div&#xA;&#xA;Invalid application key&#xA;&#xA;If the site shows a 500 error and logs show:&#xA;&#xA;preUnsupported cipher or incorrect key length/pre&#xA;&#xA;check .env:&#xA;&#xA;pregrep &#39;^APPKEY=&#39; .env/pre&#xA;&#xA;The key must be one single key. It must not look like this:&#xA;&#xA;preAPPKEY=base64:KEYONE=base64:KEYTWO/pre&#xA;&#xA;To replace it on a new install:&#xA;&#xA;prenewkey=&#34;base64:$(openssl rand -base64 32)&#34;&#xA;sudo sed -i.bak &#34;s|^APPKEY=.*|APPKEY=${newkey}|&#34; .env/pre&#xA;&#xA;Then clear the caches:&#xA;&#xA;predocker compose exec -u www-data web php artisan view:clear&#xA;docker compose exec -u www-data web php artisan config:clear&#xA;docker compose exec -u www-data web php artisan cache:clear&#xA;docker compose exec -u www-data web php artisan config:cache&#xA;docker compose restart web worker cron/pre&#xA;&#xA;div id=&#34;first-time-setup-keeps-running&#34; style=&#34;margin-top:-5px&#34;/div&#xA;&#xA;First-time setup keeps running&#xA;&#xA;If the web container keeps restarting and logs show:&#xA;&#xA;preEncryption keys already exist. Use the --force option to overwrite them./pre&#xA;&#xA;set this in .env:&#xA;&#xA;preDOCKERAPPRUNONETIMESETUPTASKS=&#34;0&#34;/pre&#xA;&#xA;Then restart:&#xA;&#xA;predocker compose down&#xA;docker compose up -d/pre&#xA;&#xA;div style=&#34;margin-top:-10px&#34;/div&#xA;&#xA;span style=&#34;font-size:0.95em;font-weight:bold;&#34;Sources:/span&#xA;span style=&#34;font-size:0.85em;&#34;Pixelfed Glitch Docker installation docs&#xA;Pixelfed Glitch configuration docs&#xA;Docker Engine Debian installation docs&#xA;Docker Linux post-installation docs&#xA;/span&#xA;&#xA;brTags: #Pixelfed #RaspberryPi]]&gt;</description>
      <content:encoded><![CDATA[<p>Although the official Pixelfed Glitch Docker docs are fairly short, I found a few rough edges when installing it on a Raspberry Pi. This guide pulls the official instructions together with the fixes I needed along the way.</p>

<p>This uses the Docker version of Pixelfed Glitch, with MariaDB and Redis running as Docker containers.</p>



<div style="margin-top:-20px"></div>

<h3 id="contents">Contents</h3>

<p><a href="#install-docker">Step 1 – Install Docker</a>
<a href="#allow-your-user-to-run-docker">Step 2 – Allow your user to run Docker</a>
<a href="#create-the-pixelfed-glitch-directory">Step 3 – Create the Pixelfed Glitch directory</a>
<a href="#download-the-docker-files">Step 4 – Download the Docker files</a>
<a href="#edit-the-environment-file">Step 5 – Edit the environment file</a>
<a href="#prepare-pixelfeds-storage-directories">Step 6 – Prepare Pixelfed&#39;s storage directories</a>
<a href="#start-pixelfed-glitch">Step 7 – Start Pixelfed Glitch</a>
<a href="#generate-the-application-and-oauth-keys">Step 8 – Generate the application and OAuth keys</a>
<a href="#stop-first-time-setup-from-running-again">Step 9 – Stop first-time setup from running again</a>
<a href="#check-the-site">Step 10 – Check the site</a>
<a href="#create-the-first-user">Step 11 – Create the first user</a>
<a href="#create-another-user">Step 12 – Create another user</a>
<a href="#useful-checks">Step 13 – Useful checks</a>
<a href="#mobile-app-login-and-2fa">Step 14 – Mobile app login and 2FA</a>
<a href="#reboot-behaviour">Step 15 – Reboot behaviour</a>
<a href="#backups">Step 16 – Backups</a>
<a href="#troubleshooting-notes">Troubleshooting notes</a></p>

<div id="install-docker" style="margin-top:-15px"></div>

<h3 id="step-1-install-docker">Step 1. Install Docker</h3>

<p>Pixelfed Glitch will run inside Docker containers. This means we do not need to manually install PHP, MariaDB, Redis, Node, Composer, or most of the other application dependencies on the Raspberry Pi itself.</p>

<p>i. Update the package list:</p>

<pre>sudo apt update &amp;&amp; sudo apt upgrade</pre>

<p>ii. Install the packages needed to add Docker&#39;s repository:</p>

<pre>sudo apt install -y ca-certificates curl</pre>

<p>iii. Create the keyrings directory:</p>

<pre>sudo install -m 0755 -d /etc/apt/keyrings</pre>

<p>iv. Download Docker&#39;s GPG key:</p>

<pre>sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc</pre>

<p>v. Make the key readable:</p>

<pre>sudo chmod a+r /etc/apt/keyrings/docker.asc</pre>

<p>vi. Add Docker&#39;s repository:</p>

<pre>sudo tee /etc/apt/sources.list.d/docker.sources &lt;&lt;EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release &amp;&amp; echo &#34;$VERSION_CODENAME&#34;)
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF</pre>

<p>vii. Update the package list again:</p>

<pre>sudo apt update</pre>

<p>viii. Install Docker and the Compose plugin:</p>

<pre>sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin</pre>

<p>ix. Check Docker is running:</p>

<pre>sudo systemctl status docker</pre>

<p>x. Enable Docker to start at boot:</p>

<pre>sudo systemctl enable docker.service
sudo systemctl enable containerd.service</pre>

<div id="allow-your-user-to-run-docker" style="margin-top:-15px"></div>

<h3 id="step-2-allow-your-user-to-run-docker">Step 2. Allow your user to run Docker</h3>

<p>By default, Docker commands need <code>sudo</code>. To run <code>docker compose</code> as your normal user, add your user to the <code>docker</code> group.</p>

<p>i. Create the group, if it does not already exist:</p>

<pre>sudo groupadd docker 2&gt;/dev/null || true</pre>

<p>ii. Add your user to it:</p>

<pre>sudo usermod -aG docker $USER</pre>

<p>iii. Log out of SSH and log back in, or reboot the Pi.</p>

<p>iv. Test Docker without <code>sudo</code>:</p>

<pre>docker run hello-world</pre>

<p>If this works, Docker is ready.</p>

<div id="create-the-pixelfed-glitch-directory" style="margin-top:-15px"></div>

<h3 id="step-3-create-the-pixelfed-glitch-directory">Step 3. Create the Pixelfed Glitch directory</h3>

<p>I installed Pixelfed Glitch under my home directory:</p>

<pre>cd /home/pi
mkdir -p pixelfed-glitch
cd pixelfed-glitch</pre>

<p>Change <code>/home/pi</code> to match your own username if needed.</p>

<div id="download-the-docker-files" style="margin-top:-15px"></div>

<h3 id="step-4-download-the-docker-files">Step 4. Download the Docker files</h3>

<p>Download the Docker Compose file and the example environment file from the Pixelfed Glitch repository:</p>

<pre>curl -fsSL https://raw.githubusercontent.com/pixelfed-glitch/pixelfed/develop/docker-compose.yml -o docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/pixelfed-glitch/pixelfed/develop/.env.docker -o .env</pre>

<p>The <code>docker-compose.yml</code> file defines the containers. The <code>.env</code> file holds site-specific settings such as the domain name, database password, upload limits, email settings, and Docker image tags.</p>

<div id="edit-the-environment-file" style="margin-top:-15px"></div>

<h3 id="step-5-edit-the-environment-file">Step 5. Edit the environment file</h3>

<p>Open the <code>.env</code> file:</p>

<pre>nano .env</pre>

<p>At minimum, change the following values.</p>

<p>Set the name of the site:</p>

<pre>APP_NAME=&#34;My Pixelfed Site&#34;</pre>

<p>Set the domain name, without <code>https://</code> and without a trailing slash:</p>

<pre>APP_DOMAIN=&#34;photos.example.com&#34;</pre>

<p>Leave <code>APP_URL</code> like this:</p>

<pre>APP_URL=&#34;https://${APP_DOMAIN}&#34;</pre>

<p>Leave <code>ADMIN_DOMAIN</code> like this:</p>

<pre>ADMIN_DOMAIN=&#34;${APP_DOMAIN}&#34;</pre>

<p>Set a public contact email address:</p>

<pre>INSTANCE_CONTACT_EMAIL=&#34;admin@example.com&#34;</pre>

<p>Set a secure database password:</p>

<pre>DB_PASSWORD=&#34;CHANGE_THIS_TO_A_LONG_RANDOM_PASSWORD&#34;</pre>

<p>If you do not plan to send email at first, you can disable mandatory email verification:</p>

<pre>ENFORCE_EMAIL_VERIFICATION=&#34;false&#34;</pre>

<p>Make sure OAuth is enabled, as this is needed for Pixelfed mobile apps:</p>

<pre>OAUTH_ENABLED=&#34;true&#34;</pre>

<p>Leave <code>APP_KEY</code> empty at this stage:</p>

<pre>APP_KEY=</pre>

<p>Pixelfed will generate this later. If you ever set it manually, it must be one single Laravel key, for example:</p>

<pre>APP_KEY=base64:CHANGE_THIS_TO_ONE_VALID_KEY_ONLY</pre>

<p>Do not paste two keys together on the same line.</p>

<div id="prepare-pixelfeds-storage-directories" style="margin-top:-15px"></div>

<h3 id="step-6-prepare-pixelfed-s-storage-directories">Step 6. Prepare Pixelfed&#39;s storage directories</h3>

<p>The Docker image expects several Laravel storage paths to exist. Creating them now avoids a startup error such as:</p>

<pre>Please provide a valid cache path.</pre>

<p>Run:</p>

<pre>cd /home/pi/pixelfed-glitch

sudo mkdir -p docker-compose-state/data/pixelfed/storage/app/public
sudo mkdir -p docker-compose-state/data/pixelfed/storage/framework/cache/data
sudo mkdir -p docker-compose-state/data/pixelfed/storage/framework/sessions
sudo mkdir -p docker-compose-state/data/pixelfed/storage/framework/testing
sudo mkdir -p docker-compose-state/data/pixelfed/storage/framework/views
sudo mkdir -p docker-compose-state/data/pixelfed/storage/logs
sudo mkdir -p docker-compose-state/data/pixelfed/storage/docker/lock
sudo mkdir -p docker-compose-state/data/pixelfed/cache

sudo chown -R 33:33 docker-compose-state/data/pixelfed/storage
sudo chown -R 33:33 docker-compose-state/data/pixelfed/cache</pre>

<p>User ID <code>33</code> is <code>www-data</code>, which is the user Pixelfed runs as inside the container.</p>

<div id="start-pixelfed-glitch" style="margin-top:-15px"></div>

<h3 id="step-7-start-pixelfed-glitch">Step 7. Start Pixelfed Glitch</h3>

<p>Start the containers:</p>

<pre>docker compose up -d</pre>

<p>This downloads the Pixelfed Glitch, MariaDB, and Redis images, creates the containers, and starts the first-time setup.</p>

<p>Check the containers:</p>

<pre>docker compose ps</pre>

<p>You should eventually see <code>web</code>, <code>worker</code>, <code>cron</code>, <code>db</code>, and <code>redis</code> as <code>Up</code>.</p>

<p>To watch the logs:</p>

<pre>docker compose logs --tail=100 --follow</pre>

<p>If you only want the web container logs:</p>

<pre>docker compose logs --tail=100 web</pre>

<div id="generate-the-application-and-oauth-keys" style="margin-top:-15px"></div>

<h3 id="step-8-generate-the-application-and-oauth-keys">Step 8. Generate the application and OAuth keys</h3>

<p>If the site shows a 500 error and the logs mention either of these:</p>

<pre>No application encryption key has been specified.
Invalid key supplied</pre>

<p>run the following commands:</p>

<pre>docker compose exec web php artisan key:generate --force
docker compose exec -u www-data web php artisan passport:keys --force</pre>

<p>Then clear and rebuild Pixelfed&#39;s cached config:</p>

<pre>docker compose exec -u www-data web php artisan view:clear
docker compose exec -u www-data web php artisan config:clear
docker compose exec -u www-data web php artisan cache:clear
docker compose exec -u www-data web php artisan config:cache</pre>

<p>Restart the Pixelfed containers:</p>

<pre>docker compose restart web worker cron</pre>

<div id="stop-first-time-setup-from-running-again" style="margin-top:-15px"></div>

<h3 id="step-9-stop-first-time-setup-from-running-again">Step 9. Stop first-time setup from running again</h3>

<p>After the first-time setup has completed and the keys have been created, edit <code>.env</code> again:</p>

<pre>nano .env</pre>

<p>Add this line:</p>

<pre>DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS=&#34;0&#34;</pre>

<p>This stops Pixelfed from trying to recreate encryption keys on every container start.</p>

<p>If this is not set, the container may restart repeatedly with an error like:</p>

<pre>Encryption keys already exist. Use the --force option to overwrite them.</pre>

<p>Restart the stack:</p>

<pre>docker compose down
docker compose up -d</pre>

<p>Do not use <code>docker compose down -v</code>, as that removes Docker volumes.</p>

<div id="check-the-site" style="margin-top:-15px"></div>

<h3 id="step-10-check-the-site">Step 10. Check the site</h3>

<p>Open your Pixelfed URL in a browser:</p>

<pre>https://photos.example.com</pre>

<p>If you are using NGINX as a reverse proxy, make sure it points to the Docker web port. In the default Pixelfed Glitch Docker file this is:</p>

<pre>8080</pre>

<p>So the proxy target is:</p>

<pre>http://127.0.0.1:8080</pre>

<p>Check the running containers:</p>

<pre>docker compose ps</pre>

<p>If you see a 502 error, the <code>web</code> container is probably not running yet, or it is restarting. Check:</p>

<pre>docker compose logs --tail=200 web</pre>

<div id="create-the-first-user" style="margin-top:-15px"></div>

<h3 id="step-11-create-the-first-user">Step 11. Create the first user</h3>

<p>Create the first account:</p>

<pre>docker compose exec -u www-data web php artisan user:create</pre>

<p>Follow the prompts.</p>

<p>To make the user an admin:</p>

<pre>docker compose exec -u www-data web php artisan user:admin USERNAME</pre>

<p>To manually verify an email address:</p>

<pre>docker compose exec -u www-data web php artisan user:verifyemail USERNAME</pre>

<p>For example:</p>

<pre>docker compose exec -u www-data web php artisan user:admin rob
docker compose exec -u www-data web php artisan user:verifyemail rob</pre>

<div id="create-another-user" style="margin-top:-15px"></div>

<h3 id="step-12-create-another-user">Step 12. Create another user</h3>

<p>Run the same create command again:</p>

<pre>docker compose exec -u www-data web php artisan user:create</pre>

<p>Follow the prompts and enter the new username.</p>

<p>For example:</p>

<pre>bnw</pre>

<p>Only run the admin command for accounts that should have admin rights.</p>

<div id="useful-checks" style="margin-top:-15px"></div>

<h3 id="step-13-useful-checks">Step 13. Useful checks</h3>

<p>Check container status:</p>

<pre>docker compose ps</pre>

<p>Show recent logs:</p>

<pre>docker compose logs --tail=200 web</pre>

<p>Check the current Pixelfed config values:</p>

<pre>docker compose exec -u www-data web php artisan tinker --execute=&#39;
echo &#34;app.url=&#34;.config(&#34;app.url&#34;).PHP_EOL;
echo &#34;oauth=&#34;.(config(&#34;pixelfed.oauth_enabled&#34;) ? &#34;true&#34; : &#34;false&#34;).PHP_EOL;
echo &#34;session.domain=&#34;.config(&#34;session.domain&#34;).PHP_EOL;
&#39;</pre>

<p>Check the application key:</p>

<pre>grep &#39;^APP_KEY=&#39; .env</pre>

<p>A valid key should look like one single line:</p>

<pre>APP_KEY=base64:LONG_RANDOM_STRING_HERE</pre>

<p>Check the OAuth key files:</p>

<pre>docker compose exec -u www-data web ls -l storage/oauth-private.key storage/oauth-public.key</pre>

<div id="mobile-app-login-and-2fa" style="margin-top:-15px"></div>

<h3 id="step-14-mobile-app-login-and-2fa">Step 14. Mobile app login and 2FA</h3>

<p>The web version worked fine for me with 2FA enabled.</p>

<p>The mobile app login flow was different. With 2FA enabled, the official Pixelfed app and Impressia both opened a web login pop-up, accepted the username, password, and 2FA code, then stayed in the web version inside the pop-up instead of returning to the app.</p>

<p>The workaround was:</p>
<ol><li>Keep 2FA enabled on the admin account.</li>
<li>Use a separate non-admin account for mobile app login.</li>
<li>Disable 2FA on that non-admin account before logging in to the apps.</li></ol>

<p>If the web interface will not disable 2FA and clicking the green “Enabled” button only adds <code>#</code> to the URL, disable it from the database.</p>

<p>First check the 2FA column names:</p>

<pre>docker compose exec -u www-data web php artisan tinker --execute=&#39;
print_r(array_values(array_filter(
    Schema::getColumnListing(&#34;users&#34;),
    fn($c) =&gt; str_contains(strtolower($c), &#34;two&#34;) || str_contains(strtolower($c), &#34;2fa&#34;) || str_contains(strtolower($c), &#34;otp&#34;)
)));
&#39;</pre>

<p>On my install the columns were:</p>

<pre>2fa_enabled
2fa_secret
2fa_backup_codes
2fa_setup_at</pre>

<p>To disable 2FA for a user called <code>bnw</code>:</p>

<pre>docker compose exec -u www-data web php artisan tinker --execute=&#39;
DB::table(&#34;users&#34;)-&gt;where(&#34;username&#34;, &#34;bnw&#34;)-&gt;update([
    &#34;2fa_enabled&#34; =&gt; false,
    &#34;2fa_secret&#34; =&gt; null,
    &#34;2fa_backup_codes&#34; =&gt; null,
    &#34;2fa_setup_at&#34; =&gt; null,
]);
echo &#34;2FA disabled for bnw\n&#34;;
&#39;</pre>

<p>After that, app login worked.</p>

<div id="reboot-behaviour" style="margin-top:-15px"></div>

<h3 id="step-15-reboot-behaviour">Step 15. Reboot behaviour</h3>

<p>The <code>docker-compose.yml</code> file uses:</p>

<pre>restart: unless-stopped</pre>

<p>This means the containers should come back up after a reboot, as long as Docker itself starts on boot.</p>

<p>Check Docker is enabled:</p>

<pre>systemctl is-enabled docker</pre>

<p>If needed:</p>

<pre>sudo systemctl enable docker</pre>

<p>After a reboot, check Pixelfed:</p>

<pre>cd /home/pi/pixelfed-glitch
docker compose ps</pre>

<p>One thing to remember: if you run this command:</p>

<pre>docker compose down</pre>

<p>the containers are removed. Docker cannot restart removed containers at boot. To recreate and start them:</p>

<pre>cd /home/pi/pixelfed-glitch
docker compose up -d</pre>

<div id="backups" style="margin-top:-15px"></div>

<h3 id="step-16-backups">Step 16. Backups</h3>

<p>At minimum, back up the Pixelfed Glitch install directory:</p>

<pre>/home/pi/pixelfed-glitch</pre>

<p>This contains:</p>

<pre>docker-compose.yml
.env
docker-compose-state/</pre>

<p>The <code>.env</code> file contains secrets, including the database password and application key, so store backups securely.</p>

<p>The <code>docker-compose-state</code> directory contains the MariaDB data, Redis data, Pixelfed storage, and cache folders. For a live database, a proper database dump is safer than only copying files while containers are running.</p>

<p>A simple manual MariaDB dump can be created with:</p>

<pre>cd /home/pi/pixelfed-glitch
docker compose exec db mariadb-dump -u pixelfed -p pixelfed_prod &gt; pixelfed_db_backup.sql</pre>

<p>You will be prompted for the database password from <code>.env</code>.</p>

<div id="troubleshooting-notes" style="margin-top:-15px"></div>

<h3 id="troubleshooting-notes">Troubleshooting notes</h3>

<p><a href="#docker-permission-denied">Docker permission denied</a>
<a href="#missing-cache-path">Missing cache path</a>
<a href="#invalid-application-key">Invalid application key</a>
<a href="#first-time-setup-keeps-running">First-time setup keeps running</a></p>

<div id="docker-permission-denied" style="margin-top:-5px"></div>

<h4 id="docker-permission-denied">Docker permission denied</h4>

<p>If you see:</p>

<pre>permission denied while trying to connect to the docker API at unix:///var/run/docker.sock</pre>

<p>your user is not in the <code>docker</code> group, or the current login session has not picked up the new group membership.</p>

<p>Fix:</p>

<pre>sudo usermod -aG docker $USER</pre>

<p>Then log out and back in.</p>

<div id="missing-cache-path" style="margin-top:-5px"></div>

<h4 id="missing-cache-path">Missing cache path</h4>

<p>If the web container restarts and logs show:</p>

<pre>Please provide a valid cache path.</pre>

<p>create the Laravel storage and cache folders from Step 6.</p>

<div id="invalid-application-key" style="margin-top:-5px"></div>

<h4 id="invalid-application-key">Invalid application key</h4>

<p>If the site shows a 500 error and logs show:</p>

<pre>Unsupported cipher or incorrect key length</pre>

<p>check <code>.env</code>:</p>

<pre>grep &#39;^APP_KEY=&#39; .env</pre>

<p>The key must be one single key. It must not look like this:</p>

<pre>APP_KEY=base64:KEY_ONE=base64:KEY_TWO</pre>

<p>To replace it on a new install:</p>

<pre>new_key=&#34;base64:$(openssl rand -base64 32)&#34;
sudo sed -i.bak &#34;s|^APP_KEY=.*|APP_KEY=${new_key}|&#34; .env</pre>

<p>Then clear the caches:</p>

<pre>docker compose exec -u www-data web php artisan view:clear
docker compose exec -u www-data web php artisan config:clear
docker compose exec -u www-data web php artisan cache:clear
docker compose exec -u www-data web php artisan config:cache
docker compose restart web worker cron</pre>

<div id="first-time-setup-keeps-running" style="margin-top:-5px"></div>

<h4 id="first-time-setup-keeps-running">First-time setup keeps running</h4>

<p>If the web container keeps restarting and logs show:</p>

<pre>Encryption keys already exist. Use the --force option to overwrite them.</pre>

<p>set this in <code>.env</code>:</p>

<pre>DOCKER_APP_RUN_ONE_TIME_SETUP_TASKS=&#34;0&#34;</pre>

<p>Then restart:</p>

<pre>docker compose down
docker compose up -d</pre>

<div style="margin-top:-10px"></div>

<p><span style="font-size:0.95em;font-weight:bold;">Sources:</span>
<span style="font-size:0.85em;"><a href="https://pixelfed-glitch.github.io/docs/running-pixelfed/docker/installation.html">Pixelfed Glitch Docker installation docs</a>
<a href="https://pixelfed-glitch.github.io/docs/configuration/configuration.html">Pixelfed Glitch configuration docs</a>
<a href="https://docs.docker.com/engine/install/debian/">Docker Engine Debian installation docs</a>
<a href="https://docs.docker.com/engine/install/linux-postinstall/">Docker Linux post-installation docs</a>
</span></p>

<p><br>Tags: <a href="https://blog.rstokes.uk/tag:Pixelfed" class="hashtag"><span>#</span><span class="p-category">Pixelfed</span></a> <a href="https://blog.rstokes.uk/tag:RaspberryPi" class="hashtag"><span>#</span><span class="p-category">RaspberryPi</span></a></p>
]]></content:encoded>
      <guid>https://blog.rstokes.uk/installing-pixelfed-glitch-on-a-raspberry-pi</guid>
      <pubDate>Sun, 05 Jul 2026 09:48:47 +0000</pubDate>
    </item>
    <item>
      <title>Categories</title>
      <link>https://blog.rstokes.uk/categories</link>
      <description>&lt;![CDATA[Use these tags to browse related posts.&#xA;&#xA;!--more--&#xA;&#xA;Climate&#xA;EndOfYearReview&#xA;F1&#xA;Mastodon&#xA;Movies&#xA;Pixelfed&#xA;RaspberryPi&#xA;Science&#xA;TV]]&gt;</description>
      <content:encoded><![CDATA[<p>Use these tags to browse related posts.</p>



<p><a href="https://blog.rstokes.uk/tag:Climate" class="hashtag"><span>#</span><span class="p-category">Climate</span></a>
<a href="https://blog.rstokes.uk/tag:EndOfYearReview" class="hashtag"><span>#</span><span class="p-category">EndOfYearReview</span></a>
<a href="https://blog.rstokes.uk/tag:F1" class="hashtag"><span>#</span><span class="p-category">F1</span></a>
<a href="https://blog.rstokes.uk/tag:Mastodon" class="hashtag"><span>#</span><span class="p-category">Mastodon</span></a>
<a href="https://blog.rstokes.uk/tag:Movies" class="hashtag"><span>#</span><span class="p-category">Movies</span></a>
<a href="https://blog.rstokes.uk/tag:Pixelfed" class="hashtag"><span>#</span><span class="p-category">Pixelfed</span></a>
<a href="https://blog.rstokes.uk/tag:RaspberryPi" class="hashtag"><span>#</span><span class="p-category">RaspberryPi</span></a>
<a href="https://blog.rstokes.uk/tag:Science" class="hashtag"><span>#</span><span class="p-category">Science</span></a>
<a href="https://blog.rstokes.uk/tag:TV" class="hashtag"><span>#</span><span class="p-category">TV</span></a></p>
]]></content:encoded>
      <guid>https://blog.rstokes.uk/categories</guid>
      <pubDate>Thu, 01 Jan 2026 00:27:31 +0000</pubDate>
    </item>
    <item>
      <title>Installing Mastodon 4.3 on a Raspberry Pi</title>
      <link>https://blog.rstokes.uk/installing-mastodon-4-3-on-a-raspberry-pi</link>
      <description>&lt;![CDATA[Although the official Mastodon installation docs are quite thorough, I did find a few quirks when installing on a Raspberry Pi (both 4B and 5). I&#39;ve brought together various guides that I used (sources are cited) into a single set of instructions which have repeatedly worked for me.&#xA;&#xA;!--more--&#xA;&#xA;div style=&#34;margin-top:-20px&#34;/div&#xA;&#xA;Contents&#xA;&#xA;a href=&#34;#increase-the-swap-file&#34;Step 1 – Increase the swap file/a&#xA;a href=&#34;#ssh-keys&#34;Step 2 – SSH Keys/a&#xA;a href=&#34;#nginx-web-server&#34;Step 3 – NGINX web server/a&#xA;a href=&#34;#ssl-certificates&#34;Step 4 – SSL certificates/a&#xA;a href=&#34;#mastodon-pre-installation&#34;Step 5 – Mastodon pre-installation/a&#xA;a href=&#34;#install-nodejs&#34;Step 6 – Install NodeJS/a&#xA;a href=&#34;#install-postgresql-and-enable-yarn&#34;Step 7 – Install PostgreSQL (and enable Yarn)/a&#xA;a href=&#34;#install-ruby&#34;Step 8 – Install Ruby/a&#xA;a href=&#34;#install-mastodon&#34;Step 9 – Install Mastodon/a&#xA;a href=&#34;#post-installation-customisation&#34;Step 10 – Post-installation customisation/a&#xA;&#xA;div id=&#34;increase-the-swap-file&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 1. Increase the swap file&#xA;&#xA;If you&#39;re using a 4GB Raspberry Pi (4B or 5), you will need to increase the size of the swap file, at least temporarily, otherwise the process (in Step 9) to compile CSS/JS assets may crash. Obviously, the 1GB and 2GB models should not be used here as they lack sufficient memory.&#xA;&#xA;You can set the swap file back to its original size—once Mastodon is installed—by following these steps again, but this is not necessary.&#xA;&#xA;⚠️ &amp;nbsp;If you&#39;re using a Raspberry Pi (4B or 5) with 8GB of RAM, you can safely skip this and move straight on to Step 2.br&#xA;&#xA;Stop the system from using the current swap file:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo dphys-swapfile swapoff/pre&#xA;&#xA;Open the swap file configuration file:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo nano /etc/dphys-swapfile/pre&#xA;&#xA;Find the following line of text within the file (value may vary):&#xA;&#xA;    pre style=&#34;margin-bottom:-22px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;CONFSWAPSIZE=200/pre&#xA;&#xA;    and change the value to 2048 (MB):&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;CONFSWAPSIZE=2048/pre&#xA;&#xA;Save the file by pressing CTRL + X, followed by Y, then Enter.&#xA;&#xA;Re-initialise the swap file (removes the original swap file and recreates it to fit the newly defined size):&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo dphys-swapfile setup/pre&#xA;&#xA;Turn the swap back on:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo dphys-swapfile swapon/pre&#xA;&#xA;Reboot the device to allow all programs to be reloaded with access to the new memory pool:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo reboot/pre&#xA;&#xA;div id=&#34;ssh-keys&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 2. SSH Keys&#xA;&#xA;Using SSH keys for authentication instead of passwords is a great way of securing the Raspberry Pi, as well as making logins much quicker.br&#xA;&#xA;Find your public SSH key on your computer. On macOS, this will be a file ending .pub in the ~/.ssh directory.&#xA;&#xA;Create a .ssh directory in your home directory on the Raspberry Pi:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;install -d -m 700 ~/.ssh/pre&#xA;&#xA;Create (and edit) an authorizedkeys file in the new directory:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;nano ~/.ssh/authorizedkeys/pre&#xA;&#xA;Paste the contents of your public SSH key into this file, then save.&#xA;&#xA;Ensure the file has the correct permissions:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo chmod 644 ~/.ssh/authorizedkeys/pre&#xA;&#xA;Ensure the file has the correct owner (if not using pi as the default user, replace it below with the name of your default user):&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo chown pi:pi ~/.ssh/authorizedkeys/pre&#xA;&#xA;div id=&#34;nginx-web-server&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 3. NGINX web server&#xA;&#xA;We want the ability to host other websites on this server so we will use NGINX as a reverse proxy for Mastodon.br&#xA;&#xA;Update the package list and upgrade existing packages:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt update &amp;&amp; sudo apt upgrade/pre&#xA;&#xA;Install NGINX:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt install -y nginx/pre&#xA;&#xA;Start the NGINX service:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo systemctl start nginx/pre&#xA;&#xA;Install PHP-FPM and recommended PHP modules:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt install -y php8.2-fpm php8.2-mbstring php8.2-mysql php8.2-curl php8.2-gd php8.2-zip php8.2-xml/pre&#xA;&#xA;div id=&#34;ssl-certificates&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 4. SSL certificates&#xA;&#xA;I am using Cloudflare for DNS and tunnelling so I need to follow these steps to create and deploy an Origin CA certificate.&#xA;&#xA;⚠️ &amp;nbsp;If you don&#39;t use Cloudflare, install your own SSL certificate here instead of following the exact instructions below.br&#xA;&#xA;Log in to the Cloudflare dashboard and select an account.&#xA;&#xA;Choose your domain.&#xA;&#xA;Go to SSL/TLS   Origin Server.&#xA;&#xA;Select Create Certificate.&#xA;&#xA;Choose Generate private key and CSR with Cloudflare and leave all other options as they are. Click the Create button.&#xA;&#xA;Ensure the Key Format is PEM and then copy the signed Origin Certificate and Private Key into separate .pem and .key files. Click the OK button.&#xA;&#xA;Copy the .pem and .key files to your Raspberry Pi in the /etc/ssl directory.&#xA;&#xA;Change the owner of both files to root:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo chown root:root /etc/ssl/filename.key /etc/ssl/filename.pem/pre&#xA;&#xA;Restart NGINX:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo systemctl restart nginx/pre&#xA;&#xA;10. Back in the Cloudflare dashboard, go to SSL/TLS   Overview and click Configure. Under the option Custom SSL/TLS click Select. Change the option to Full (Strict) and click Save.&#xA;&#xA;div id=&#34;mastodon-pre-installation&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 5. Mastodon pre-installationbr&#xA;&#xA;Update and upgrade system packages:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt update &amp;&amp; sudo apt upgrade/pre&#xA;&#xA;Install dependencies:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt install -y curl lsb-release 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 certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev/pre&#xA;&#xA;Create a mastodon user:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo useradd mastodon -m/pre&#xA;&#xA;div id=&#34;install-nodejs&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 6. Install NodeJSbr&#xA;&#xA;Update the package list and upgrade existing packages:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt update &amp;&amp; sudo apt upgrade/pre&#xA;&#xA;To ensure we have all of the packages we need to access the Nodesource repository, run the following command:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt install -y ca-certificates curl gnupg/pre&#xA;&#xA;Download the Nodesource GPG key and store it within the /usr/share/keyrings directory:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;curl -fsSL httpsnolink://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/nodesource.gpg/pre&#xA;&#xA;Set an environment variable that we will reference next:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;NODEMAJOR=20/pre&#xA;&#xA;Add the NodeJS repository to your sources list:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;echo &#34;deb [signed-by=/usr/share/keyrings/nodesource.gpg] httpsnolink://deb.nodesource.com/node$NODEMAJOR.x nodistro main&#34; | sudo tee /etc/apt/sources.list.d/nodesource.list/pre&#xA;&#xA;Since we made changes to the sources list, we need to update the package list:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt update/pre&#xA;&#xA;Install the NodeJS package:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt install -y nodejs/pre&#xA;&#xA;div id=&#34;install-postgresql-and-enable-yarn&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 7. Install PostgreSQL (and enable Yarn)br&#xA;&#xA;Save the GPG key for the PostgreSQL repository:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;curl -L httpsnolink://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | sudo tee /usr/share/keyrings/postgresql-archive-keyring.gpg   /dev/null/pre&#xA;&#xA;Add the repository to our sources list:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;echo &#34;deb [arch=arm64 signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] httpnolink://apt.postgresql.org/pub/repos/apt $(lsbrelease -cs)-pgdg main&#34; | sudo tee  /etc/apt/sources.list.d/postgresql.list/pre&#xA;&#xA;As we changed the available repositories, we need to update the package list cache again:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt update/pre&#xA;&#xA;Install the PostgreSQL package:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo apt install -y postgresql postgresql-contrib/pre&#xA;&#xA;Launch the PostgreSQL command line interface (CLI):&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo -u postgres psql/pre&#xA;&#xA;Create a PostgreSQL user named mastodon:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;CREATE USER mastodon CREATEDB;/pre&#xA;&#xA;Quit out of the CLI:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;\q/pre&#xA;&#xA;To build and run Mastodon, we need to enable Yarn (the NodeJS package manager). Do this now:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo corepack enable &amp;&amp; sudo yarn set version classic/pre&#xA;&#xA;div id=&#34;install-ruby&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 8. Install Rubybr&#xA;&#xA;Switch to the mastodon user:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo su mastodon/pre&#xA;&#xA;Change to the home directory:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;cd ~/pre&#xA;&#xA;Clone the code repository for the rbenv utility:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;git clone httpsnolink://github.com/rbenv/rbenv.git ~/.rbenv/pre&#xA;&#xA;Clone the code repository for the ruby-build plugin:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;git clone httpsnolink://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build/pre&#xA;&#xA;Adjust the .bashrc file to initialise the rbenv utility to set up the Ruby environment:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;echo &#39;eval &#34;$(~/.rbenv/bin/rbenv init - bash)&#34;&#39;     ~/.bashrc/pre&#xA;&#xA;To ensure the changes we made are available immediately:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;exec bash/pre&#xA;&#xA;Install Ruby 3.3.5:&#xA;&#xA;    pre style=&#34;margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;RUBYCONFIGUREOPTS=--with-jemalloc rbenv install 3.3.5/pre&#xA;&#xA;    ##### ⚠️ &amp;nbsp;This step can take a long time to complete.&#xA;&#xA;Declare the installed Ruby version 3.3.5 as the global version to use:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;rbenv global 3.3.5/pre&#xA;&#xA;Use the Ruby package manager to install bundler:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;gem install bundler --no-document/pre&#xA;&#xA;div id=&#34;install-mastodon&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 9. Install Mastodonbr&#xA;&#xA;Make sure that you are still running as the mastodon user; switch to that user now, if not:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo su mastodon/pre&#xA;&#xA;Change to the home directory:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;cd ~/pre&#xA;&#xA;Clone the code repository for Mastodon, then change to the new live directory:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;git clone httpsnolink://github.com/mastodon/mastodon.git live &amp;&amp; cd live/pre&#xA;&#xA;Change to the latest stable release of Mastodon:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;git checkout $(git tag -l | grep &#39;^v[0-9.]$&#39; | sort -V | tail -n 1)/pre&#xA;&#xA;Set the deployment option to true and exclude any packages that are only used for development or test purposes:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;bundle config deployment &#39;true&#39; &amp;&amp; bundle config without &#39;development test&#39;/pre&#xA;&#xA;Install all of the Ruby dependencies for Mastodon:&#xA;&#xA;    pre style=&#34;margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;bundle install -j$(nproc)/pre&#xA;&#xA;    Note: we use the -j option to tell the package manager to use as many CPU cores as we have.&#xA;&#xA;Install all of the NodeJS dependencies for Mastodon:&#xA;&#xA;    pre style=&#34;margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;yarn install/pre&#xA;&#xA;    ##### ⚠️ &amp;nbsp;You can safely ignore any warnings thrown here.&#xA;&#xA;Configure Mastodon:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;RAILSENV=production bundle exec rake mastodon:setup/pre&#xA;&#xA;Follow the on-screen prompts for how you would like to set up Mastodon. You can leave the PostgreSQL and Redis options as default (just press Enter on each option).&#xA;&#xA;10. Switch back to your default user:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;exit/pre&#xA;&#xA;11. Update the default NGINX host file using the template provided on the Mastodon docs website, or replace the file with a copy of a previously backed-up host file.&#xA;&#xA;12. Reload NGINX web server:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo systemctl reload nginx/pre&#xA;&#xA;13. Copy the systemd services for Mastodon to the relevant directory:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo cp /home/mastodon/live/dist/mastodon-.service /etc/systemd/system//pre&#xA;&#xA;14. Start the services now and enable them to start automatically at logon in future:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming/pre&#xA;&#xA;div id=&#34;post-installation-customisation&#34; style=&#34;margin-top:-15px&#34;/div&#xA;&#xA;Step 10. Post-installation customisation (optional)&#xA;&#xA;a href=&#34;#import-a-blocklist&#34;Import a blocklist/a&#xA;a href=&#34;#change-the-maximum-post-length-and-poll-limit&#34;Change the maximum post length and poll limit/a&#xA;a href=&#34;#change-the-username-display-name-and-notes-limits&#34;Change the username, display name, and notes limits/a&#xA;&#xA;div id=&#34;import-a-blocklist&#34; style=&#34;margin-top:-30px&#34;/div&#xA;&#xA;Import a blocklist&#xA;&#xA;Download this blocklist.&#xA;&#xA;In Mastodon, go to Moderation   Federation and click on the Import button at the top of the page.&#xA;&#xA;Choose the blocklist file you previously downloaded and click Upload.&#xA;&#xA;You should now see a long list of domain blocks. Make sure the Select All checkbox is selected and then click on Import.&#xA;&#xA;div id=&#34;change-the-maximum-post-length-and-poll-limit&#34; style=&#34;margin-top:-25px&#34;/div&#xA;&#xA;Change the maximum post length and poll limit&#xA;&#xA;Switch to the mastodon user:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo su mastodon/pre&#xA;&#xA;Change to the home directory:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;cd ~/pre&#xA;&#xA;Edit the compose\form\container.js file:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;nano -w live/app/javascript/mastodon/features/compose/containers/composeformcontainer.js/pre&#xA;&#xA;Search for the line:&#xA;&#xA;    pre style=&#34;margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;maxChars: state.getIn([&#39;server&#39;, &#39;server&#39;, &#39;configuration&#39;, &#39;statuses&#39;, &#39;maxcharacters&#39;], 500)/pre&#xA;&#xA;    and change the value 500 to the new limit (e.g. 2000).&#xA;&#xA;Save the file by pressing CTRL + X, followed by Y, then Enter.&#xA;&#xA;Edit the status\length\validator.rb file:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;nano -w live/app/validators/statuslengthvalidator.rb/pre&#xA;&#xA;Search for the line:&#xA;&#xA;    pre style=&#34;margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;MAXCHARS = 500/pre&#xA;&#xA;    and change the value 500 to the same new limit as above.&#xA;&#xA;Save the file by pressing CTRL + X, followed by Y, then Enter.&#xA;&#xA;Edit the poll\options\validator.rb file:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;nano -w live/app/validators/polloptionsvalidator.rb/pre&#xA;&#xA;10. Search for the line:&#xA;&#xA;    pre style=&#34;margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;MAXOPTIONS = 4/pre&#xA;&#xA;    and change the value 4 to the new limit (e.g. 12).&#xA;&#xA;11. Save the file by pressing CTRL + X, followed by Y, then Enter.&#xA;&#xA;12. Rebuild the assets:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;cd live &amp;&amp; RAILSENV=production bundle exec rails assets:precompile/pre&#xA;&#xA;13. Switch back to the main user:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;exit/pre&#xA;&#xA;14. Restart the Mastodon services:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo systemctl restart mastodon-sidekiq mastodon-web mastodon-streaming/pre&#xA;&#xA;div id=&#34;change-the-username-display-name-and-notes-limits&#34; style=&#34;margin-top:-25px&#34;/div&#xA;&#xA;Change the username, display name, and notes limits&#xA;&#xA;Switch to the mastodon user:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo su mastodon/pre&#xA;&#xA;Change to the home directory:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;cd ~/pre&#xA;&#xA;Edit the account.rb file:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;nano -w live/app/models/account.rb/pre&#xA;&#xA;Search for the following lines and amend as required:&#xA;&#xA;    pre style=&#34;margin-bottom:-50px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;USERNAMELENGTHLIMIT = 30/pre&#xA;&#xA;    pre style=&#34;margin-bottom:-50px;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;DISPLAYNAMELENGTHLIMIT = 30/pre&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;NOTELENGTH_LIMIT = 500/pre&#xA;&#xA;Save the file by pressing CTRL + X, followed by Y, then Enter.&#xA;&#xA;Restart the Mastodon services:&#xA;&#xA;    pre style=&#34;white-space:pre-wrap;font-size:1em;font-weight:bold;&#34;sudo systemctl restart mastodon-sidekiq mastodon-web mastodon-streaming/pre&#xA;&#xA;div style=&#34;margin-top:-10px&#34;/div&#xA;&#xA;span style=&#34;font-size:0.95em;font-weight:bold;&#34;Sources:/spanspan style=&#34;font-size:0.85em;&#34;&#xA;Increasing Swap on a Raspberry Pi&#xA;How to Setup SSH Keys on your Raspberry Pi&#xA;Build your own Raspberry Pi NGINX Web Server&#xA;Cloudflare origin CA&#xA;How to create a CSR using OpenSSL &amp; install your SSL certificate on a Nginx server&#xA;Installing Mastodon on the Raspberry Pi&#xA;Installing NodeJS on the Raspberry Pi&#xA;Mastodon blocklists&#xA;Increasing the Mastodon post character and poll options limit&#xA;/span&#xA;&#xA;brTags: #Mastodon #RaspberryPi]]&gt;</description>
      <content:encoded><![CDATA[<p>Although the official Mastodon installation docs are quite thorough, I did find a few quirks when installing on a Raspberry Pi (both 4B and 5). I&#39;ve brought together various guides that I used (sources are cited) into a single set of instructions which have repeatedly worked for me.</p>



<div style="margin-top:-20px"></div>

<h3 id="contents">Contents</h3>

<p><a href="#increase-the-swap-file">Step 1 – Increase the swap file</a>
<a href="#ssh-keys">Step 2 – SSH Keys</a>
<a href="#nginx-web-server">Step 3 – NGINX web server</a>
<a href="#ssl-certificates">Step 4 – SSL certificates</a>
<a href="#mastodon-pre-installation">Step 5 – Mastodon pre-installation</a>
<a href="#install-nodejs">Step 6 – Install NodeJS</a>
<a href="#install-postgresql-and-enable-yarn">Step 7 – Install PostgreSQL (and enable Yarn)</a>
<a href="#install-ruby">Step 8 – Install Ruby</a>
<a href="#install-mastodon">Step 9 – Install Mastodon</a>
<a href="#post-installation-customisation">Step 10 – Post-installation customisation</a></p>

<div id="increase-the-swap-file" style="margin-top:-15px"></div>

<h3 id="step-1-increase-the-swap-file">Step 1. Increase the swap file</h3>

<p>If you&#39;re using a <strong>4GB</strong> Raspberry Pi (4B or 5), you will need to increase the size of the swap file, at least temporarily, otherwise the process (in Step 9) to compile CSS/JS assets may crash. Obviously, the 1GB and 2GB models should <strong>not</strong> be used here as they lack sufficient memory.</p>

<p>You can set the swap file back to its original size—once Mastodon is installed—by following these steps again, but this is not necessary.</p>

<h5 id="nbsp-if-you-re-using-a-raspberry-pi-4b-or-5-with-8gb-of-ram-you-can-safely-skip-this-and-move-straight-on-to-step-2-br">⚠️  If you&#39;re using a Raspberry Pi (4B or 5) with 8GB of RAM, you can safely skip this and move straight on to Step 2.<br></h5>
<ol><li><p>Stop the system from using the current swap file:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo dphys-swapfile swapoff</pre></li>

<li><p>Open the swap file configuration file:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo nano /etc/dphys-swapfile</pre></li>

<li><p>Find the following line of text within the file (value may vary):</p>

<pre style="margin-bottom:-22px;white-space:pre-wrap;font-size:1em;font-weight:bold;">CONF_SWAPSIZE=200</pre>

<p>and change the value to 2048 (MB):</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">CONF_SWAPSIZE=2048</pre></li>

<li><p>Save the file by pressing <strong>CTRL + X</strong>, followed by <strong>Y</strong>, then <strong>Enter</strong>.</p></li>

<li><p>Re-initialise the swap file (removes the original swap file and recreates it to fit the newly defined size):</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo dphys-swapfile setup</pre></li>

<li><p>Turn the swap back on:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo dphys-swapfile swapon</pre></li>

<li><p>Reboot the device to allow all programs to be reloaded with access to the new memory pool:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo reboot</pre></li></ol>

<div id="ssh-keys" style="margin-top:-15px"></div>

<h3 id="step-2-ssh-keys">Step 2. SSH Keys</h3>

<p>Using SSH keys for authentication instead of passwords is a great way of securing the Raspberry Pi, as well as making logins much quicker.<br></p>
<ol><li><p>Find your public SSH key on your computer. On macOS, this will be a file ending <strong>.pub</strong> in the <strong>~/.ssh</strong> directory.</p></li>

<li><p>Create a <strong>.ssh</strong> directory in your home directory on the Raspberry Pi:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">install -d -m 700 ~/.ssh</pre></li>

<li><p>Create (and edit) an <strong>authorized_keys</strong> file in the new directory:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">nano ~/.ssh/authorized_keys</pre></li>

<li><p>Paste the contents of your public SSH key into this file, then save.</p></li>

<li><p>Ensure the file has the correct permissions:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo chmod 644 ~/.ssh/authorized_keys</pre></li>

<li><p>Ensure the file has the correct owner (if not using <strong>pi</strong> as the default user, replace it below with the name of your default user):</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo chown pi:pi ~/.ssh/authorized_keys</pre></li></ol>

<div id="nginx-web-server" style="margin-top:-15px"></div>

<h3 id="step-3-nginx-web-server">Step 3. NGINX web server</h3>

<p>We want the ability to host other websites on this server so we will use NGINX as a reverse proxy for Mastodon.<br></p>
<ol><li><p>Update the package list and upgrade existing packages:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt update &amp;&amp; sudo apt upgrade</pre></li>

<li><p>Install NGINX:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt install -y nginx</pre></li>

<li><p>Start the NGINX service:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo systemctl start nginx</pre></li>

<li><p>Install PHP-FPM and recommended PHP modules:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt install -y php8.2-fpm php8.2-mbstring php8.2-mysql php8.2-curl php8.2-gd php8.2-zip php8.2-xml</pre></li></ol>

<div id="ssl-certificates" style="margin-top:-15px"></div>

<h3 id="step-4-ssl-certificates">Step 4. SSL certificates</h3>

<p>I am using Cloudflare for DNS and tunnelling so I need to follow these steps to create and deploy an Origin CA certificate.</p>

<h5 id="nbsp-if-you-don-t-use-cloudflare-install-your-own-ssl-certificate-here-instead-of-following-the-exact-instructions-below-br">⚠️  If you don&#39;t use Cloudflare, install your own SSL certificate here instead of following the exact instructions below.<br></h5>
<ol><li><p>Log in to the Cloudflare dashboard and select an account.</p></li>

<li><p>Choose your domain.</p></li>

<li><p>Go to <strong>SSL/TLS &gt; Origin Server</strong>.</p></li>

<li><p>Select <strong>Create Certificate</strong>.</p></li>

<li><p>Choose <strong>Generate private key and CSR with Cloudflare</strong> and leave all other options as they are. Click the <strong>Create</strong> button.</p></li>

<li><p>Ensure the <strong>Key Format</strong> is <strong>PEM</strong> and then copy the signed <strong>Origin Certificate</strong> and <strong>Private Key</strong> into separate <strong>.pem</strong> and <strong>.key</strong> files. Click the <strong>OK</strong> button.</p></li>

<li><p>Copy the <strong>.pem</strong> and <strong>.key</strong> files to your Raspberry Pi in the <strong>/etc/ssl</strong> directory.</p></li>

<li><p>Change the owner of both files to <strong>root</strong>:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo chown root:root /etc/ssl/filename.key /etc/ssl/filename.pem</pre></li>

<li><p>Restart NGINX:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo systemctl restart nginx</pre></li>

<li><p>Back in the Cloudflare dashboard, go to <strong>SSL/TLS &gt; Overview</strong> and click <strong>Configure</strong>. Under the option <strong>Custom SSL/TLS</strong> click <strong>Select</strong>. Change the option to <strong>Full (Strict)</strong> and click <strong>Save</strong>.</p></li></ol>

<div id="mastodon-pre-installation" style="margin-top:-15px"></div>

<h3 id="step-5-mastodon-pre-installation-br">Step 5. Mastodon pre-installation<br></h3>
<ol><li><p>Update and upgrade system packages:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt update &amp;&amp; sudo apt upgrade</pre></li>

<li><p>Install dependencies:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt install -y curl lsb-release 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 certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev</pre></li>

<li><p>Create a <strong>mastodon</strong> user:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo useradd mastodon -m</pre></li></ol>

<div id="install-nodejs" style="margin-top:-15px"></div>

<h3 id="step-6-install-nodejs-br">Step 6. Install NodeJS<br></h3>
<ol><li><p>Update the package list and upgrade existing packages:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt update &amp;&amp; sudo apt upgrade</pre></li>

<li><p>To ensure we have all of the packages we need to access the Nodesource repository, run the following command:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt install -y ca-certificates curl gnupg</pre></li>

<li><p>Download the Nodesource GPG key and store it within the <strong>/usr/share/keyrings</strong> directory:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/nodesource.gpg</pre></li>

<li><p>Set an environment variable that we will reference next:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">NODE_MAJOR=20</pre></li>

<li><p>Add the NodeJS repository to your sources list:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">echo &#34;deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main&#34; | sudo tee /etc/apt/sources.list.d/nodesource.list</pre></li>

<li><p>Since we made changes to the sources list, we need to update the package list:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt update</pre></li>

<li><p>Install the NodeJS package:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt install -y nodejs</pre></li></ol>

<div id="install-postgresql-and-enable-yarn" style="margin-top:-15px"></div>

<h3 id="step-7-install-postgresql-and-enable-yarn-br">Step 7. Install PostgreSQL (and enable Yarn)<br></h3>
<ol><li><p>Save the GPG key for the PostgreSQL repository:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">curl -L https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | sudo tee /usr/share/keyrings/postgresql-archive-keyring.gpg &gt;/dev/null</pre></li>

<li><p>Add the repository to our sources list:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">echo &#34;deb [arch=arm64 signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main&#34; | sudo tee  /etc/apt/sources.list.d/postgresql.list</pre></li>

<li><p>As we changed the available repositories, we need to update the package list cache again:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt update</pre></li>

<li><p>Install the PostgreSQL package:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo apt install -y postgresql postgresql-contrib</pre></li>

<li><p>Launch the PostgreSQL command line interface (CLI):</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo -u postgres psql</pre></li>

<li><p>Create a PostgreSQL user named <strong>mastodon</strong>:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">CREATE USER mastodon CREATEDB;</pre></li>

<li><p>Quit out of the CLI:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">\q</pre></li>

<li><p>To build and run Mastodon, we need to enable Yarn (the NodeJS package manager). Do this now:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo corepack enable &amp;&amp; sudo yarn set version classic</pre></li></ol>

<div id="install-ruby" style="margin-top:-15px"></div>

<h3 id="step-8-install-ruby-br">Step 8. Install Ruby<br></h3>
<ol><li><p>Switch to the <strong>mastodon</strong> user:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo su mastodon</pre></li>

<li><p>Change to the <em>home</em> directory:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">cd ~</pre></li>

<li><p>Clone the code repository for the <em>rbenv</em> utility:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">git clone https://github.com/rbenv/rbenv.git ~/.rbenv</pre></li>

<li><p>Clone the code repository for the <em>ruby-build</em> plugin:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build</pre></li>

<li><p>Adjust the <em>.bashrc</em> file to initialise the <em>rbenv</em> utility to set up the Ruby environment:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">echo &#39;eval &#34;$(~/.rbenv/bin/rbenv init - bash)&#34;&#39; &gt;&gt; ~/.bashrc</pre></li>

<li><p>To ensure the changes we made are available immediately:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">exec bash</pre></li>

<li><p>Install Ruby 3.3.5:</p>

<pre style="margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;">RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.3.5</pre>

<h5 id="nbsp-this-step-can-take-a-long-time-to-complete">⚠️  This step can take a long time to complete.</h5></li>

<li><p>Declare the installed Ruby version 3.3.5 as the global version to use:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">rbenv global 3.3.5</pre></li>

<li><p>Use the Ruby package manager to install <em>bundler</em>:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">gem install bundler --no-document</pre></li></ol>

<div id="install-mastodon" style="margin-top:-15px"></div>

<h3 id="step-9-install-mastodon-br">Step 9. Install Mastodon<br></h3>
<ol><li><p>Make sure that you are still running as the <strong>mastodon</strong> user; switch to that user now, if not:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo su mastodon</pre></li>

<li><p>Change to the <em>home</em> directory:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">cd ~</pre></li>

<li><p>Clone the code repository for Mastodon, then change to the new <em>live</em> directory:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">git clone https://github.com/mastodon/mastodon.git live &amp;&amp; cd live</pre></li>

<li><p>Change to the <strong>latest stable release</strong> of Mastodon:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">git checkout $(git tag -l | grep &#39;^v[0-9.]*$&#39; | sort -V | tail -n 1)</pre></li>

<li><p>Set the <em>deployment</em> option to true and exclude any packages that are only used for development or test purposes:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">bundle config deployment &#39;true&#39; &amp;&amp; bundle config without &#39;development test&#39;</pre></li>

<li><p>Install all of the Ruby dependencies for Mastodon:</p>

<pre style="margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;">bundle install -j$(nproc)</pre>

<p><em>Note: we use the -j option to tell the package manager to use as many CPU cores as we have.</em></p></li>

<li><p>Install all of the NodeJS dependencies for Mastodon:</p>

<pre style="margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;">yarn install</pre>

<h5 id="nbsp-you-can-safely-ignore-any-warnings-thrown-here">⚠️  You can safely ignore any warnings thrown here.</h5></li>

<li><p>Configure Mastodon:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">RAILS_ENV=production bundle exec rake mastodon:setup</pre></li>

<li><p>Follow the on-screen prompts for how you would like to set up Mastodon. You can leave the PostgreSQL and Redis options as default (just press <strong>Enter</strong> on each option).</p></li>

<li><p>Switch back to your default user:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">exit</pre></li>

<li><p>Update the default NGINX host file using the template provided on the Mastodon docs website, or replace the file with a copy of a previously backed-up host file.</p></li>

<li><p>Reload NGINX web server:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo systemctl reload nginx</pre></li>

<li><p>Copy the <em>systemd</em> services for Mastodon to the relevant directory:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/</pre></li>

<li><p>Start the services now and enable them to start automatically at logon in future:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming</pre></li></ol>

<div id="post-installation-customisation" style="margin-top:-15px"></div>

<h3 id="step-10-post-installation-customisation-optional">Step 10. Post-installation customisation <em>(optional)</em></h3>

<p><a href="#import-a-blocklist">Import a blocklist</a>
<a href="#change-the-maximum-post-length-and-poll-limit">Change the maximum post length and poll limit</a>
<a href="#change-the-username-display-name-and-notes-limits">Change the username, display name, and notes limits</a></p>

<div id="import-a-blocklist" style="margin-top:-30px"></div>

<h3 id="import-a-blocklist">Import a blocklist</h3>
<ol><li><p>Download <a href="https://github.com/sgrigson/oliphant/blob/main/blocklists/mastodon/_unified_tier0_blocklist.csv">this blocklist</a>.</p></li>

<li><p>In Mastodon, go to <strong>Moderation</strong> &gt; <strong>Federation</strong> and click on the <strong>Import</strong> button at the top of the page.</p></li>

<li><p>Choose the blocklist file you previously downloaded and click <strong>Upload</strong>.</p></li>

<li><p>You should now see a long list of domain blocks. Make sure the <strong>Select All</strong> checkbox is selected and then click on <strong>Import</strong>.</p></li></ol>

<div id="change-the-maximum-post-length-and-poll-limit" style="margin-top:-25px"></div>

<h3 id="change-the-maximum-post-length-and-poll-limit">Change the maximum post length and poll limit</h3>
<ol><li><p>Switch to the <strong>mastodon</strong> user:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo su mastodon</pre></li>

<li><p>Change to the <em>home</em> directory:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">cd ~</pre></li>

<li><p>Edit the <em>compose_form_container.js</em> file:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">nano -w live/app/javascript/mastodon/features/compose/containers/compose_form_container.js</pre></li>

<li><p>Search for the line:</p>

<pre style="margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;">maxChars: state.getIn([&#39;server&#39;, &#39;server&#39;, &#39;configuration&#39;, &#39;statuses&#39;, &#39;max_characters&#39;], 500)</pre>

<p>and change the value <strong>500</strong> to the new limit (e.g. 2000).</p></li>

<li><p>Save the file by pressing <strong>CTRL + X</strong>, followed by <strong>Y</strong>, then <strong>Enter</strong>.</p></li>

<li><p>Edit the <em>status_length_validator.rb</em> file:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">nano -w live/app/validators/status_length_validator.rb</pre></li>

<li><p>Search for the line:</p>

<pre style="margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;">MAX_CHARS = 500</pre>

<p>and change the value <strong>500</strong> to the same new limit as above.</p></li>

<li><p>Save the file by pressing <strong>CTRL + X</strong>, followed by <strong>Y</strong>, then <strong>Enter</strong>.</p></li>

<li><p>Edit the <em>poll_options_validator.rb</em> file:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">nano -w live/app/validators/poll_options_validator.rb</pre></li>

<li><p>Search for the line:</p>

<pre style="margin-bottom:-25px;white-space:pre-wrap;font-size:1em;font-weight:bold;">MAX_OPTIONS = 4</pre>

<p>and change the value <strong>4</strong> to the new limit (e.g. 12).</p></li>

<li><p>Save the file by pressing <strong>CTRL + X</strong>, followed by <strong>Y</strong>, then <strong>Enter</strong>.</p></li>

<li><p>Rebuild the assets:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">cd live &amp;&amp; RAILS_ENV=production bundle exec rails assets:precompile</pre></li>

<li><p>Switch back to the main user:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">exit</pre></li>

<li><p>Restart the Mastodon services:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo systemctl restart mastodon-sidekiq mastodon-web mastodon-streaming</pre></li></ol>

<div id="change-the-username-display-name-and-notes-limits" style="margin-top:-25px"></div>

<h3 id="change-the-username-display-name-and-notes-limits">Change the username, display name, and notes limits</h3>
<ol><li><p>Switch to the <strong>mastodon</strong> user:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo su mastodon</pre></li>

<li><p>Change to the <em>home</em> directory:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">cd ~</pre></li>

<li><p>Edit the <em>account.rb</em> file:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">nano -w live/app/models/account.rb</pre></li>

<li><p>Search for the following lines and amend as required:</p>

<pre style="margin-bottom:-50px;white-space:pre-wrap;font-size:1em;font-weight:bold;">USERNAME_LENGTH_LIMIT = 30</pre>

<pre style="margin-bottom:-50px;white-space:pre-wrap;font-size:1em;font-weight:bold;">DISPLAY_NAME_LENGTH_LIMIT = 30</pre>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">NOTE_LENGTH_LIMIT = 500</pre></li>

<li><p>Save the file by pressing <strong>CTRL + X</strong>, followed by <strong>Y</strong>, then <strong>Enter</strong>.</p></li>

<li><p>Restart the Mastodon services:</p>

<pre style="white-space:pre-wrap;font-size:1em;font-weight:bold;">sudo systemctl restart mastodon-sidekiq mastodon-web mastodon-streaming</pre></li></ol>

<div style="margin-top:-10px"></div>

<p><span style="font-size:0.95em;font-weight:bold;">Sources:</span><span style="font-size:0.85em;">
<a href="https://pimylifeup.com/raspberry-pi-swap-file">Increasing Swap on a Raspberry Pi</a>
<a href="https://pimylifeup.com/raspberry-pi-ssh-keys">How to Setup SSH Keys on your Raspberry Pi</a>
<a href="https://pimylifeup.com/raspberry-pi-nginx">Build your own Raspberry Pi NGINX Web Server</a>
<a href="https://developers.cloudflare.com/ssl/origin-configuration/origin-ca">Cloudflare origin CA</a>
<a href="https://www.digicert.com/kb/csr-ssl-installation/nginx-openssl.htm">How to create a CSR using OpenSSL &amp; install your SSL certificate on a Nginx server</a>
<a href="https://pimylifeup.com/raspberry-pi-mastodon">Installing Mastodon on the Raspberry Pi</a>
<a href="https://pimylifeup.com/raspberry-pi-nodejs">Installing NodeJS on the Raspberry Pi</a>
<a href="https://github.com/sgrigson/oliphant/tree/main/blocklists/mastodon">Mastodon blocklists</a>
<a href="https://fouquet.me/2024/10/10/mastodon-4-3-char-limit">Increasing the Mastodon post character and poll options limit</a>
</span></p>

<p><br>Tags: <a href="https://blog.rstokes.uk/tag:Mastodon" class="hashtag"><span>#</span><span class="p-category">Mastodon</span></a> <a href="https://blog.rstokes.uk/tag:RaspberryPi" class="hashtag"><span>#</span><span class="p-category">RaspberryPi</span></a></p>
]]></content:encoded>
      <guid>https://blog.rstokes.uk/installing-mastodon-4-3-on-a-raspberry-pi</guid>
      <pubDate>Sun, 20 Oct 2024 21:02:53 +0000</pubDate>
    </item>
  </channel>
</rss>