I’ve recently been able to set up Lemmy and PieFed instances on a Raspberry Pi 5 and wanted to share the process for anyone else interested in self hosting an instance.

The following instructions are based off using a used Raspberry Pi 5 (ARM64) plus a USB external hard drive for the hardware. I used the Raspberry Pi 5 image which is based off Debian 12. The following instructions should be similar enough for other Debian 12 distributions and should hopefully get the same results.

The only other purchase I’ve made was a domain name which was super cheap ($15 a year which includes hiding WHOIS information). Everything else is free.

My residential ISP service blocks incoming data on “business” ports such as Port 80 and 443. Users won’t be able to access your site securely if these ports block incoming data. To work around this I used Cloudflare Tunnels. This allows users to access your site normally. Cloudflare Tunnel will send incoming data to a port of your choosing (between 1024-65,535) and users can access your self-hosted instance.

Cloudflare also has Top Layer Security (TLS) which encrypts traffic and protects connections. This also means your website goes from HTTP:// to HTTPS:// in the address bar. Federation will require TLS so this will be useful. Cloudflare Tunnel also introduces some complications which I’ll address later.

Edited Feb 1/2025
Changed PieFed cron jobs to match recent changes
Adjusted RSync sections

  • taters@piefed.socialOP
    link
    fedilink
    English
    arrow-up
    3
    ·
    edit-2
    4 days ago

    Lemmy (LOCAL HOST)

    The lemmy instructions are simple and straight forward. When changing the fields asked of you in the instructions, it’s helpful to search and replace the required fields. In nano when editing a file, press CTRL + \ and follow the instructions at the bottom of the window. This will find and replace text.

    The Lemmy instructions show text for editing with {{ Example }}. To avoid confusion, those curly braces must be removed and replaced with the expected data.

    • If you used NPM’s login page to test Cloudflare Tunnels, you will need to login to NPM and change the Port Forward from 81 to 10633
      • Click Hosts -> Proxy Hosts -> Click the 3-Dots for your DOMAINNAME.COM proxy rule -> Edit & Save
    1. Follow Lemmy Install Instructions
      • IGNORE steps Reverse Proxy/Webserver & Let’s Encrypt since we have addressed those steps earlier with NPM and Cloudflare Tunnels/Security.
    2. Through a Web Browser, type in your DOMAINNAME.COM and you should see an admin creation page. Complete that and the initial instance setup afterwards.
    3. Test federation, replace capitals with the required information
      • curl -H 'Accept: application/activity+json' https://DOMAINNAME.COM/u/LEMMY_USERNAME

        • If you see .json information, Lemmy is federated
        • If you see .html information, lemmy is NOT federated

    Updating Lemmy Docker Container

    See here for more information.

    1. docker compose down
    2. docker compose pull
    3. docker compose up -d

    PieFed (LOCAL HOST)

    The PieFed installation instructions will provide more detailed information about each step. This guide does NOT cover any email setup for PieFed.

    • If you used NPM’s login page to test Cloudflare Tunnels, you will need to login to NPM and change the Port Forward from 81 to 8030

      • Click Hosts -> Proxy Hosts -> Click the 3-Dots for your DOMAINNAME.COM proxy rule -> Edit & Save
    • PieFed Install Instructions

    1. Download & Prepare files
      1. git clone https://codeberg.org/rimu/pyfedi.git
      2. cd pyfedi
      3. cp env.docker.sample .env.docker
    2. Edit & Save files
      1. nano .env.docker
        1. Change value for SECRET_KEY with random numbers and letters
        2. Change value for SERVER_NAME with your DOMAINNAME.COM
      2. nano compose.yaml
        • Note ports 8030:5000. You can change the external container port: 8030: if you are using a custom port. Do NOT touch the internal container port :5000.
          • ports:
          • - '8030:5000'
    3. Build
      1. export DOCKER_BUILDKIT=1
      2. sudo docker compose up --build
        • Wait until text stops scrolling
    4. Access your DOMAINNAME.COM from a Web Browser
      1. You may see a message that says database system is ready to accept connections in your terminal window after PieFed is done installing and loading. This means you are ready to attempt a connection through your Web Browser now.
        • If you see constant permission errors, Open and SSH login to the Raspberry Pi in a new terminal window and do the following to allow PieFed to access the required folders:
          1. cd ~/pyfedi
          2. chown -R USERNAME:USERNAME ./pgdata
            • You can leave this window open, it can be used for the step 5.
      2. You may see an “Internal Server Error” after your first connection attempt. This is normal. You will see movement in your terminal window on each attempt to connect to PieFed. Now you can proceed to initialize the database.
    5. Initialize Database
      1. Open and SSH login to the Raspberry Pi in a new terminal window
        1. sudo docker exec -it piefed_app1 sh
        2. export FLASK_APP=pyfedi.py
        3. flask init-db
          • Enter username/email/password. Email is optional.
        4. Access PieFed from your Web Browser again. PieFed should now display. You can log in as admin with the same username and password.
        5. exit
        6. You can close this terminal window now
    6. Return to the terminal with the running docker build and press CTRL + C to stop PieFed.
    7. Run PieFed in the background
      • docker-compose up -d
    8. Setup Cron (Automated) Tasks
      • This will set up automated tasks for daily maintenance, weekly maintenance and email notifications.
      • Change USERNAME to your username.
      1. Setup automated tasks
        1. sudo nano /etc/cron.d/piefed
          1. Paste and Save
    • /etc/cron.d/piefed file
    5 2 * * * USERNAME docker exec piefed_app1 bash -c "cd /app && ./daily.sh"  
    5 4 * * 1 USERNAME docker exec piefed_app1 bash -c "cd /app && ./remove_orphan_files.sh"  
    1 */6 * * * USERNAME docker exec piefed_app1 bash -c "cd /app && ./email_notifs.sh"  
    
    • taters@piefed.socialOP
      link
      fedilink
      English
      arrow-up
      3
      ·
      5 days ago

      …Continued from PieFed Instructions…

      Cloudflare Website Settings

      These settings are suggested to help manage traffic. See here for more detailed information.

      1. Exclude Settings
        1. From the main page -> Your DOMAINNAME.COM -> Security -> WAF -> Custom Rules -> Click Create Rule -> Change the following settings and values on Cloudflare to match what’s listed below:
          • Rule Name: Allow Inbox
          • Field: URI Path
          • Operator: contains
          • Value: /inbox
          • Log matching requests: On
          • Then take action…: Skip
          • WAF components to skip: All remaining custom rules
        2. Click `Deploy’ to complete
      2. Caching Settings
        1. From the main page -> Your DOMAINNAME.COM -> Caching -> Cache Rules -> Click Create rule -> Change the following settings on Cloudflare to match what’s listed below:
          • Rule name: ActivityPub
          1. Custom filter expressions: On
            1. Field: URI Path
            2. Operator: Starts with
            3. Value: /activities/
          2. Click Or
          3. Repeat until you have values for 4 rules total containing the values:
            • /activities/
            • /api/
            • /nodeinfo/
            • /.well-known/webfinger
          • Cache Eligibility: On
          • Edge TTL -> Click + add setting
            • Click Ignore cache-control header and use this TTL
            • Input time-to-live (TTL): 2 hours
          • Click Deploy to complete
        2. Click Create rule again
          • Rule name: ActivityPub2
          1. Custom filter expressions: On
            1. Field: Request Header
            2. Name: accept
            3. Operator: contains
            4. Value: application/activity+json
          2. Click Or
          3. Repeat until you have 2 rules total containing the values:
            • application/activity+json
            • application/ld+json
          • Cache Eligibility: On
          • Edge TTL -> Click + add setting
            • Click Ignore cache-control header and use this TTL
            • Input time-to-live (TTL): Type 10 seconds
          • Click Deploy to complete
      3. Optimization Settings
        1. Speed -> Optimization -> Content Optimization -> Change the following settings on Cloudflare to match what’s listed below:
          • Speed Brain: Off
          • Cloudflare Fonts: Off
          • Early Hints: Off
          • Rocket Loader: Off
      4. Cloudflare Tokens for .env.docker File
        1. Create an API “Zone.Cache Purge” token
          1. After logging in to Cloudflare, go to this page
          2. Click Create Token -> Click Get Started under Create Custom Token
          3. Token Name -> PieFed
          4. Under Permissions -> Change the following drop down menu’s to match what’s listed below
            • First drop down menu: Zone
            • Second drop down menu: Cache Purge
            • Third drop down menu: Purge
          5. Click Continue to summary -> Click Create Token
          6. Copy the generated API Token. This will be used for CLOUDFLARE_API_TOKEN in the .env.docker file. Note, once you leave this screen, the API token will remain but the generated code that can be copied will disappear forever.
        2. Copy API Zone ID
          1. From the main page -> Your DOMAINNAME.COM -> Scroll down and look for API Zone ID in the far right column
          2. Copy API Zone ID Token. This will be used for CLOUDFLARE_ZONE_ID in the .env.docker File.
        3. The following step must be completed on the Raspberry Pi (LOCAL HOST) where PieFed is running:
          1. nano ~/pyfedi/.env.docker
            1. Add the following lines with your copied API Tokens & Save
              • CLOUDFLARE_API_TOKEN = 'ZONE.CACHE_PURGE_TOKEN'
              • CLOUDFLARE_ZONE_ID = 'API_ZONE_ID_TOKEN'
          2. Restart PieFed Docker container
            • docker compose down && docker compose up -d

      Troubleshooting

      • If you receive an error while posting images, the folder permissions will need to change. Change USERNAME with your username.
        1. cd ~/pyfedi
        2. sudo chown -R USERNAME:USERNAME ./media
      • taters@piefed.socialOP
        link
        fedilink
        English
        arrow-up
        4
        ·
        edit-2
        4 days ago

        Backup/Restore Setup

        I decided to keep it simple and use the rsync command which comes already installed on Raspberry Pi OS. The guide linked below does a good job of explaining rsync in a step by step process.

        Below the linked guide I’ll provide an example of the commands I use to Backup and Restore my raspberry Pi. This creates a copy of the /rootfs folders that make up your Raspberry Pi Operating System and User folders. The commands will exclude some folders that may cause issues when restoring a backup. The guide linked below has more details.

        Since I am going to power down the Pi and physically connect it’s hard drive to my computer, I don’t have to worry about making backups on a live and running storage.

        The below commands assume I also have an additional EXTERNAL_STORAGE hard drive connected to my computer. This means the backup command will copy the contents from the Raspberry Pi drive (/rootfs folder) to the EXTERNAL_STORAGE drive (/EXTERNAL_STORAGE/backup folder). The restore command will copy the contents from the EXTERNAL_STORAGE drive (/EXTERNAL_STORAGE/backup/rootfs folder) to the Raspberry Pi drive (/rootfs folder)

        rsync WILL delete data on the target location to sync all files and folders from the source location. Be mindful of which direction you are going to avoid any losses. I suggest testing it out on some other folders before commiting to backing up and restoring the entire Raspberry Pi. The guide linked below also covers exclusions to minimize backup sizes.

        The backup storage MUST be formatted in EXT4 to make sure file permissions and attributes remain the same.

        1. nano ~/.bash_aliases
          1. Add comments & Save
            • alias rsyncBACKUP="sudo rsync -avxhP --delete --exclude={'proc/','sys/','dev/','tmp/','run/','mnt/','media/','home/USERNAME/.cache','lost+found'} /media/USERNAME/rootfs /media/USERNAME/EXTERNAL_STORAGE/backup/"
            • rsyncRESTORE="sudo rsync -avxhP --delete --exclude={'proc/','sys/','dev/','tmp/','run/','mnt/','media/','home/USERNAME/.cache','lost+found'} /media/USERNAME/EXTERNAL_STORAGE/backup/rootfs/ /media/USERNAME/rootfs"
        2. Reset bash in terminal
          • . ~/.bashrc
        3. Backup system TO EXTERNAL_STORAGE
          • !!EXT4 file system only!!
          • rsBACKUP
        4. Restore system FROM EXTERNAL_STORAGE
          • rsRESTORE

        Firewall (LOCAL HOST)

        1. Install: Choose ONE
          • Command line only
            • sudo apt install -y ufw
          • Graphical Interface with command line access
            • sudo apt install -y gufw

        I haven’t figured out how to properly set this up for myself yet, but I figure it’s probably worth having for an additional layer of protection.

    • taters@piefed.socialOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      4 days ago

      …Continued from PieFed Instructions…

      1. OPTIONAL: Environment Variables
        • Some functions such as email or captcha’s won’t work unless you add the necessary variables into the ~/pyfedi/.env.docker file. Look at ~/pyfedi/env.sample and add the other variables to ~/pyfedi/.env.docker according to your needs.
        1. View the sample file
          • nano ~/pyfedi/env.sample
        2. Edit & Save .env.docker file
          • nano ~/pyfedi/.env.docker
        3. Restart PieFed Docker container
          • docker compose down && docker compose up -d

      Updating PieFed Docker Container

      1. docker compose down
      2. git pull
      3. docker compose up --build
      4. docker compose down && docker compose up -d