The other week I had written about Pixelfed and my plans for using it. Since this is self-hosted software and I spent a fair amount of time setting it up, I wanted to write out a detailed installation guide. Hopefully, it helps someone else out there looking to create their own setup.
Starting with the basics
The basics of my setup are:
- An Intel i3 Intel NUC machine 1
- Running Ubuntu Linux 20.04
Begin with the Pixelfed Repo
Start here: https://github.com/pixelfed
Clone that repository locally on your machine. This article is based upon the Pixelfed v0.11.2 release.
Make a few changes:
"beyondcode/laravel-self-diagnosis": "^1.5". This is needed because of issue #3150. Hopefully this is fixed in Pixelfed v0.11.3+!
docker-compose.ymlfor the worker service. It’s possible this is not needed, but I added it during a troubleshooting step and figure better safe than sorry.
Once those changes are complete, run
docker-compose build. This will use the Dockerfile from the repository to build docker images. You can examine the Dockerfile by looking at what is specified in the
build: context: . dockerfile: contrib/docker/Dockerfile.apache image: pixelfed
Your Docker Compose File
With the Pixelfed image built, turn your attention to the other services spec’d in the
First off, switch the
db service to use mariadb.
db: image: mariadb:latest
With v0.11.2 of Pixelfed I initially tried and failed to use MySQL. I found this Github issue #2989 which explains the problem I was seeing, and perhaps there are other problems with using MySQL.
Next, start your containers with
docker-compose up -d. Give them a second to load, and check their status with
With the containers running follow Pixelfed’s install guide.
Pixelfed Install Guide Steps
A very useful reference is Pixelfed’s Installation Guide. Please note: there is a potential re-write of this guide coming sometime in 2022, as mentioned in Pixelfed’s Discord server.
From the guide, use these specific sections:
- Configure environment variables
- Setting up services
Follow Pixelfed’s instructions to set
These are my general settings:
## General Settings APP_NAME="Pixelfed" APP_ENV=production APP_DEBUG=false APP_URL=https://pix.mattedwards.org APP_DOMAIN="pix.mattedwards.org" ADMIN_DOMAIN="pix.mattedwards.org" SESSION_DOMAIN="pix.mattedwards.org"
Note that the URL is a full URL, while the domains are simply the host info.
Side note on hosting and DNS: Depending on where you are installing Pixelfed (your own homelab server, or a cloud droplet like DigitalOcean or Linode) you should consider how that domain name you are giving to Pixelfed is being resolved and routed. Are you using Traefik as a reverse proxy for your homelab server? Explaining that is beyond the scope of this article, but is important to think about!
For the database settings, you can use the MYSQL_* settings with MariaDB. There are MariaDB specific environment variables but when not supplied the MySQL ones are used instead. Make sure to set a strong database password (even for these internally-hosted services behind a reverse proxy!). If you change the database port, make sure other containers are appropriately configured.
## Databases (MySQL) DB_CONNECTION=mysql DB_DATABASE=pixelfed_prod DB_HOST=db DB_PASSWORD=<<REPLACE_WITH_YOUR_PASSWORD>> DB_PORT=3306 DB_USERNAME=pixelfed # pass the same values to the db itself MYSQL_DATABASE=pixelfed_prod MYSQL_PASSWORD=<<REPLACE_WITH_YOUR_PASSWORD>> MYSQL_RANDOM_ROOT_PASSWORD=true MYSQL_USER=pixelfed
I left the Postgres values commented out in the file. You may choose to delete them, if you prefer.
For redis make sure to choose a strong password.
## Cache (Redis) REDIS_CLIENT=phpredis REDIS_SCHEME=tcp REDIS_HOST=redis REDIS_PASSWORD=<<REPLACE_WITH_YOUR_PASSWORD>> REDIS_PORT=6379 REDIS_DATABASE=0
For ActivityPub federation, which allows you to follow different Pixelfed servers - and even Mastodon servers! - you can set these flags to true. If you’re simply experimenting and would rather not risk exposing your server to the Fediverse just yet, you can leave these set to their default FALSE values and flip them TRUE later on.
## ActivityPub Federation ACTIVITY_PUB=true AP_REMOTE_FOLLOW=true AP_SHAREDINBOX=true AP_INBOX=true AP_OUTBOX=true ATOM_FEEDS=true NODEINFO=true WEBFINGER=true
Finally, a few miscellaneous settings I have enabled.
INSTANCE_PUBLIC_HASHTAGS=true should be allowing my hashtags to be available to all users (right now, it’s just me!).
INSTANCE_PUBLIC_LOCAL_TIMELINE=true enables a public timeline, so I can share my public posts.
STORIES_ENABLED=true Instagram-like Stories functionality, enabled mostly for fun.
APP_TIMEZONE=America/New_York to ensure my post times are accurate.
OPEN_REGISTRATION=false as I do not want rando’s registering on my personal Pixelfed instance. If I wanted to give someone access, I’ll create an account for them via the command line.
Setting up Services
These tasks need only be performed one time following the initial setup. You can run all of these commands in a specific container using this syntax:
docker-compose exec CONTAINER COMMAND
Which tells docker-compose to run COMMAND within the specified CONTAINER. Note that both the
worker containers share an image and volume storage; running a command in either one should be fine and I have not noticed a difference.
To start, generate an
APP_KEY using the app container:
docker-compose exec app php artisan key:generate
This key prints out to the command line and should be automatically inserted into your
.env.docker configuration file. Verify by opening the file.
Next, link your storage:
docker-compose exec app php artisan storage:link
Run database migrations. This would need to be done again when upgrading Pixelfed to a newer version, as well.
docker-compose exec app php artisan migrate --force
Enable support for location on posts. This is just a simple list of common cities and does not include places.
docker-compose exec app php artisan import:cities
If you chose to enable ActivityPub Federation run the below. If not, you can always do this later.
docker-compose exec app php artisan instance:actor
According to Pixelfed’s docs, “Routes should be cached whenever the source code changes or whenever you change routes. Every time you edit your .env file, cache config.” So now run:
docker-compose exec app php artisan route:cache docker-compose exec app php artisan view:cache docker-compose exec app php artisan config:cache
Finally, we must deal with Job Queueing. I got this working with Laravel Horzion, and have no experience with or opinion on Queue Worker.
docker-compose exec worker php artisan horizon:install docker-compose exec worker php artisan horizon:publish docker-compose restart worker
Note that I’m switching to the
worker container in the above commands. The purpose of this container is to run Laravel Horzion. You can see this in the
docker-compose.yml line which tells the container to run it at start:
command: gosu www-data php artisan horizon
The Pixelfed guide includes steps to setup a systemd job which runs Horizon. You need not do that with the docker setup. The
worker container is handling the Horizon queues.
The final command above was to restart the
worker container. Horizon is now running.
- I skipped setting up email since I’m planning on this being a private instance just for me. On the cheap you could setup your gmail account with an app password, or you could configure any SMTP solution you like.
My setup runs self-hosted on that little Intel NUC sitting atop my desk. I route traffic to it using Traefik Proxy.
I will not get into detail in this post on how to configure Traefik, but I will share my docker labels being used. These labels are applied on the
labels: - "traefik.enable=true" - "traefik.docker.network=web" - "traefik.http.routers.pixelfed.rule=Host(`pix.mattedwards.org`)" - "traefik.http.routers.pixelfed.entryPoints=secure" - "traefik.http.routers.pixelfed.tls=true" - "traefik.http.routers.pixelfed.service=pixelfed" - "traefik.http.services.pixelfed.loadbalancer.server.port=80" - "traefik.http.services.pixelfed.loadbalancer.server.scheme=http"
From top to bottom, these labels are doing the following:
- Enabling this container and telling Traefik to route traffic to it via my
- Identifying that Traefik should send requests for the host
pix.mattedwards.orgcoming in via secure entry point (TLS/443).
- Naming the service, so in the final labels I can tell Traefik to route traffic to Pixelfed on port 80 via http.
Getting the first user
With Pixelfed up, running, and route-able you can now configure one or more users. I prefer to do this via the command line. I do not need to register users via the web and I do not need to worry about having a working email provider to send out user account confirmation emails.
Contains a quick run-down of the user management commands.
docker-compose exec app php artisan user:create
Now, follow the prompts. Ensure that email verification = yes, to avoid having to send an email and confirm the user. If this is your first user / yourself, choose the Make Admin option.
Public profile pages
You can easily link to someone’s public profile. Images they post with Public visibility will show up here. Here is mine!
Other Excellent Resources
Specific model is BOXNUC8i3BEK1. ↩︎