Pixelfed! An ethical alternative to Instagram. Ethical because this decentralized network is run by enthusiastic users as moderators instead of the “Grow at all costs” corporation, which will be compelled to use your data against your own goodwill if that churns enough profits for them.
The best thing about Pixelfed is that, it’s open source, and it’s self-hostable. If you have some spare space on your servers, you could spin up a Pixelfed server and interact with the rest of the Fediverse. Isn’t that cool? I recently spun up a Pixelfed instance on my server, and this is an explanatory post about the steps required to host an instance for yourself on your server. Let’s dive in, shall we?
Before we could dive in…
Note: The instructions mentioned in this post concerns with Pixelfed version 0.11.3 with additional commits upto 352500f . I can’t guarentee the instructions will ever work for the uncoming releases. Feel free to get in touch with me at Mastodon or Email if necessary.
Environment Setup
Assuming that you have installed docker and docker-compose on your server, the next thing to note is to set up an .env file for docker-compose of Pixelfed. My .env file for my self-hosted instance is as follows
APP_NAME="Pixelfed"
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://pixelfed.lhin.space
APP_DOMAIN="pixelfed.lhin.space"
ADMIN_DOMAIN="pixelfed.lhin.space"
SESSION_DOMAIN="pixelfed.lhin.space"
TRUST_PROXIES="*"
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=mariadb
DB_PORT=3306
DB_DATABASE=somedatabase # Change this
DB_USERNAME=someusername # Change this
DB_PASSWORD=somepassword # Change this
PUID=1000
PGID=1000
MYSQL_DATABASE=somedatabase # Change this
MYSQL_USER=someusername # Change this
MYSQL_PASSWORD=somepassword # Change this
MYSQL_ROOT_PASSWORD=somepassword # Change this
BROADCAST_DRIVER=redis
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_DRIVER=redis
REDIS_SCHEME=tcp
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
# For this setup, you could add any email config as your email provider.
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mail.host
MAIL_PORT=587
MAIL_USERNAME=mailbox@server.name
MAIL_PASSWORD=somepassword
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=mailbox@server.name
MAIL_FROM_NAME=Pixelfed
OPEN_REGISTRATION=false
ENFORCE_EMAIL_VERIFICATION=true
PF_MAX_USERS=1000
MAX_PHOTO_SIZE=15000
MAX_CAPTION_LENGTH=150
MAX_ALBUM_LENGTH=4
ACTIVITY_PUB=true
AP_REMOTE_FOLLOW=true
AP_SHAREDINBOX=true
AP_INBOX=true
AP_OUTBOX=true
ATOM_FEEDS=true
NODEINFO=true
WEBFINGER=true
HORIZON_DARKMODE=true
HORIZON_EMBED=true
INSTANCE_CONTACT_EMAIL=admin@server.name
OAUTH_ENABLED=true
ENABLE_CONFIG_CACHE=false
.env.pixelfed
- Create a file
.env.pixelfed
in your server directory. - Copy the contents from the above to the
.env.pixelfed
file.
Make sure to replace the values mentioned under *change this *with the respective values that the database and mail server complies with. Once this .env file is all set and done, we move on to docker-compose setup.
Docker Setup
The following is my docker-compose.yml file. I’m using the zknt/pixelfed image from the Dockerhub, since it’s the most downloaded and actively maintained image of Pixelfed, yet.
version: '3'
networks:
internal:
internal: true
web:
driver: bridge
external: true
volumes:
pixelfed_redis:
external: true
pixelfed_mariadb:
external: true
pixelfed_storage:
external: true
pixelfed_bootstrap:
external: true
services:
app:
container_name: pixelfed-app
image: zknt/pixelfed:2022-08-06
restart: unless-stopped
env_file:
- .env.pixelfed
volumes:
- pixelfed_storage:/var/www/storage
- pixelfed_bootstrap:/var/www/bootstrap
- ./.env.pixelfed:/var/www/.env
networks:
- web
- internal
depends_on:
- mariadb
- redis
labels:
- traefik.enable=true
- traefik.http.routers.pixelfed.rule=Host(`pixelfed.lhin.space`)
- traefik.http.routers.pixelfed.tls=true
- traefik.http.routers.pixelfed.service=pixelfed
- traefik.http.routers.pixelfed.tls.certresolver=lets-encrypt
- traefik.http.services.pixelfed.loadbalancer.server.port=80
worker:
container_name: pixelfed-worker
image: zknt/pixelfed:2022-08-04
restart: unless-stopped
env_file:
- .env.pixelfed
volumes:
- pixelfed_storage:/var/www/storage
- pixelfed_bootstrap:/var/www/bootstrap
- ./.env.pixelfed:/var/www/.env
networks:
- web
- internal
depends_on:
- mariadb
- redis
entrypoint: /worker-entrypoint.sh
healthcheck:
test: php artisan horizon:status | grep running
interval: 60s
timeout: 5s
retries: 1
mariadb:
image: ghcr.io/linuxserver/mariadb:alpine-version-10.5.9-r0
container_name: pixelfed-mariadb
restart: always
networks:
- internal
env_file:
- .env.pixelfed
volumes:
- pixelfed_mariadb:/config:rw
redis:
image: redis:5-alpine
container_name: pixelfed-redis
restart: unless-stopped
env_file:
- .env.pixelfed
volumes:
- pixelfed_redis:/data
networks:
- internal
docker-compose.yml
Copy the following contents to a docker-compose.yml
file and keep it in the same directory as the .env.pixelfed
file. Change the contents as it pleases you. This is all you need to set up a Pixelfed instance on your server.
Note: Since I’m using traefik to manage my docker images, I tend to have a
web
network that binds with the traefik docker image. You could use other reverse proxies by removing thelabels
in theapp
service and by addingports: - 80:8080
. In this you are redirecting the traffic coming to port 8080 to the docker port 80. More info here
Pre-requisites
In order to run Pixelfed, we need to create external docker volumes first. You could also use bind mounts to local directory. But I tend to use volumes so that I don’t have to fiddle around with permission issues. The following commands will create four volumes.
docker volume create pixelfed_bootstrap
docker volume create pixelfed_storage
docker volume create pixelfed_mariadb
docker volume create pixelfed_redis
create-volume.sh
Voilà!
Now for the climax, you need to run docker-compose up -d
(?)
Well, not so fast. You need to do so in steps so that the MariaDB and the Redis is set up properly.
- First, you need to run
docker-compose up -d mariadb redis
. This will set up the MariaDB and Redis instance. You could also dodocker-compose logs -f
to check the logs and see what’s cooking in there. - Once that’s done, you should run
docker-compose up -d app
. This will spin up the app instance and run all the database migrations that are required. - Next, You need to run
docker-compose up -d worker
. This will spin up theworker
instance which will be responsible for Remote fetching account avatars and other ActivityPub stuff.
Once this is done, you could check the logs using docker-compose logs -f
to see if there are any errors in the installation. If not, we move on to the next step.
Server Setup
Firstly, you need to create an app key. Run docker-compose exec app php artisan key:generate
to generate an app key. This key will be added to your .env.pixelfed
file in base64
format.
Now that the instance is set up properly, we need to create an admin user. You could do so by running docker-compose exec app php artisan user:create
. Then answer the prompts given on the screen, and you are done.
Troubleshooting
- Empty user profiles: For a brief moment, I had an issue of getting an empty user profile when remote account is being fetched. It was fixed by running
docker-compose exec app php artisan passport:install
on my server as mentioned in this issue.
Closing Thoughts
I’m very optimistic about a future where decentralized social media like, Pixelfed, Mastodon and the entirety of Fediverse is a thing. I hope to see this pick up steam among the netizens, and also hope to see the service itself becomes accessible to anyone and everyone. For that to happen, this is my small contribution to anyone who wants to spin up a server for themselves. Feel free to contact me for any assistance.
Have a nice day :)