UNDERSTANDING THIS GUIDE:
These are commands
<?php echo "This is code, or the content of a file!" ?>
These are notes that you should read.
What is Pixelfed?
Pixelfed is an application/service similar to Instagram, but unlike Instagram, Pixelfed is not centralized, it is free and open source.
What does it mean that it is not centralized?
Unlike other services and applications, Pixelfed is decentralized, it does not depend on a single entity and each instance is unique and independent.
Also, each Pixelfed instance can interact with other instances, since it uses open protocols.
Let’s get started!
Required packages
Before configuring everything we will install some packages necessary to make everything work, instead of installing them all together, we will do it independently to avoid any problem.
Run:
apt install git zip psmisc build-essential apache2 mariadb-server curl htop bmon mc pngquant optipng jpegoptim gifsicle ffmpeg redis
System user for Pixelfed
We will create a user for the application, we execute the following:
useradd pixelfed -m -d /www/pixelfed -s /bin/false -r -c "Pixelfed User"
We obtain a copy of Github
For this we will use the user that we have already created, we execute:
su -l pixelfed -s /bin/bash ; cd
And we execute:
git clone -b dev https://github.com/pixelfed/pixelfed.git pixelfed
We should see something like this:
Clonando en 'pixelfed'... remote: Enumerating objects: 47808, done. remote: Total 47808 (delta 0), reused 0 (delta 0), pack-reused 47808 Recibiendo objetos: 100% (47808/47808), 44.17 MiB | 13.14 MiB/s, listo. Resolviendo deltas: 100% (30423/30423), listo.
(My system is in Spanish)
*I found a BUG!
There is a bug in the code of the version » dev 0.11.4″, this is due to the change of version of Laravel from 8 to 9. What causes the BUG is that when a file is uploaded and directories are created within «storage», these are created with permissions «0700», which prevents any user other than the owner of the directory, can not access it. To solve this I have requested a PULL, in the GitHUB repository #3825, which makes that the user with which PHP is executed at the moment creates the directories with the correct permissions.
To check if this has been corrected, we edit the file «pixelfed/config/filesystems.php».
We look for the lines:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
We add the following lines (In red, if they are not there they must be added):
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0644,
'private' => 0644,
],
'dir' => [
'public' => 0755,
'private' => 0755,
],
],
'public' => [
Save the file and continue.
We stop using the user «pixelfed».
NOTE: Working Directory
The working directory can change according to each one and their preferences, in my case for the WEB applications and WEB sites, I prefer to install everything in a single directory inside the RAIZ of the disk, in my case it is the «/www» and the applications in a directory with its respective name, in this case «pixelfed».
To do this we execute this command:
mkdir /www/pixelfed/ssl -p
«-p» this option will create the parent directories if they do not exist.
«ssl» we will use this directory to store the certificates signed by Let’s Encrypt.
Configuring Apache2
We will configure the apache web server, so that it can access to «/www/pixelfed», by default the apache service has permissions to work in the directory «/var/www/», we will change this so that the service can access to «www» (this is my example, in your case it can be the directory that ).
Edit the file «/etc/apache2/apache2.conf». Look for the lines:
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
We can change them or add:
<Directory /www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Configure the Virtual Host
Inside the directory «/etc/apache2/sites-available» the configurations of each virtual host are stored, we will create a new configuration called «pixelfed.conf», for example.
Considering that in this example we will use the domain «pixelfed.int» and the working directory «/www/pixelfed/public», they are all loaded in this example.
We create the file «/etc/apache2/sites-available/pixelfed.conf» and add the following:
<VirtualHost *:80>
ServerName pixelfed.int
ServerAdmin goxonline@arguos.com
DocumentRoot /www/pixelfed/pixelfed/public
LogLevel debug
<Directory /www/pixelfed/pixelfed/public>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/pidexfed.error.log
CustomLog ${APACHE_LOG_DIR}/pixelfed.access.log combined
<FilesMatch \.php$>
SetHandler "proxy:unix:/var/run/php.pixelfed.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>
We activate the site by executing:
a2ensite pixelfed.conf
And we restart the Apache service:
service apache2 restart
SSL support
This configuration example is for the service without SSL. If we need SSL, we will also create the following configuration file «/etc/apache2/sites-available/ssl.pixelfed.conf» and add the following to the file:
<VirtualHost *:443>
ServerName pixelfed.int
ServerAdmin goxonline@arguos.com
DocumentRoot /www/pixelfed/pixelfed/public
<Directory /www/pixelfed/pixelfed/public>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/var/run/php.pixelfed.sock|fcgi://localhost"
</FilesMatch>
SSLCertificateFile /www/pixelfed/ssl/fullchain.cer
SSLCertificateKeyFile /www/pixelfed/ssl/pixelfed.key
Include /etc/apache2/conf-available/letsencrypt.conf
ErrorLog ${APACHE_LOG_DIR}/ssl.pixelfed.error.log
CustomLog ${APACHE_LOG_DIR}/ssl.pixelfed.access.log combined
</VirtualHost>
We also create the file «/etc/apache2/conf-available/letsencrypt.conf» and add to it:
SSLEngine on
# Intermediate configuration, tweak to your needs
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
#SSLCipherSuite HIGH:MEDIUM:!MD5!EXP:!NULL:!LOW:!ADH
#SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder on
SSLCompression off
SSLOptions +StrictRequire
Before activating this configuration, we will request the signature of the certificate. The steps to do this are at the end of the document.
Sign a certificate for our domain with ACME.SH
We will download the client «acme.sh», but you can use any client, I am used to this one.
You can download it from here:
Release Normal release · acmesh-official/acme.sh · GitHub
Unzip the «acme.sh» in the directory of your choice, inside you will find the script «acme.sh». Psociblemente we will have to register, for this we execute:
./acme.sh --register-account --insecure --force --email test@test.com
And then we sign the certificate for our domain:
./acme.sh --issue -d pixelfed.int -w /www/pixelfed/pixelfed/public --cert-file /www/pixelfed/ssl/pixelfed.int.cer \
--key-file /www/pixelfed/ssl/pixelfed.int.key --ca-file /www/pixelfed/ssl/ca.cer \
--fullchain-file /www/pixelfed/ssl/fullchain.cer --force
(where pixelfed.int should be replaced by your domain)
We will activate the Virtual Hosts in apache with the following command:
a2ensite ssl.pixelfed.conf
We will also activate the Apache «proxy» modules, which we will use to pass the PHP files from Apache and process them. We will also activate the «Rewrite» module, which is required by Pixelfed. We execute the following command to activate the modules:
a2enmod proxy* rewrite ssl
And we restart the Apache service with the following command:
systemctl restart apache2
PHP 8.1
We add the alternative PHP repository
Repository: In order to install PHP 8.1 we will use the packages from https://deb.sury.org. To do this we will execute the following steps:
apt install apt-transport-https lsb-release ca-certificates
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
apt update
Install PHP 8.1 with the following command (The repository has several versions of PHP, so we specify the version we need):
apt-get install php8.1-fpm php8.1 php8.1-common php8.1-cli php8.1-gd php8.1-mbstring php8.1-xml php8.1-bcmath php8.1-pgsql php8.1-curl php8.1-xml php8.1-xmlrpc php8.1-imagick php8.1-gd php8.1-mysql php8.1-cli php8.1-intl php8.1-zip php8.1-redis
Configure PHP FPM
We will create a new PHP pool for our WEB site. For this we will create the file «/etc/php/8.1/fpm/pool.d/pixelfed.conf» and add the following content:
[pixelfed]
user = pixelfed
group = pixelfed
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
listen = /var/run/php.pixelfed.sock
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 20
chdir = /www/pixelfed
php_flag[display_errors] = on
php_admin_value[error_log] = /www/pixelfed/php.error.log
php_admin_flag[log_errors] = on
php_admin_value[open_basedir] = /www/pixelfed:/usr/share/:/tmp:/var/lib/php
Modify the php.ini
Edit the file «/etc/php/8.1/fpm/php.ini», find the entry «upload_max_filesize = 2M» and modify it to:
upload_max_filesize = 20M
(20 Megas is enough, this is the parameter that indicates the maximum size that a file can have. If you want to upload videos to your instance, this number should be higher).
We look for the entry «post_max_size = 8M» and modify it:
post_max_size = 20M
(It must have the same value as «upload_max_filesize»).
Save the file and continue restarting PHP-FPM service with the following command:
service php8.1-fpm restart
If there are no errors, we verify with the following command that the php is running:
pstree -cupa | grep php
We should see something like this:
|-php-fpm8.1,1392
| |-php-fpm8.1,1397,www-data
| |-php-fpm8.1,1398,www-data
| |-php-fpm8.1,1393,pixelfed
| |-php-fpm8.1,1394,pixelfed
| |-php-fpm8.1,1395,pixelfed
| `-php-fpm8.1,1396,pixelfed
| |-grep,1405 php
Create a MySQL database
We will create a database for Pixelfed called «pixelfed» (but you can create the one you want). For this as the user «root» we enter to mysql, it should not request password, since MariaDB, does not request it for the system user «root»:
:~# mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 30
Server version: 10.5.15-MariaDB-0+deb11u1 Debian 11
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
Once inside the MySQL client, we execute the following statement to create the database:
CREATE DATABASE pixelfed ;
Now we will create a user for the application that has permissions to work in this database.
GRANT ALL ON pixelfed.* TO pixelfed@localhost IDENTIFIED BY 'the_secure_password';
Note that «the_secure_password» should be changed to a slightly more secure password.
To exit the MySQL client, you can type «exit;».
Install PHP Composer
Run the following to install the PHP composer package:
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
We move the package to finish:
mv composer.phar /usr/local/bin/composer
We finish configuring Pixelfed
We use the user «pixelfed» again, executing:
su -l pixelfed -s /bin/bash ; cd
We verify the permissions of the directories and files, execute:
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
This will correct any errors in file and directory permissions that are not covered by Github.
Install the dependencies
(Even with the user pixelfed)
cd /www/pixelfed/pixelfed ; composer install --no-ansi --no-interaction --optimize-autoloader
Note: We may also need to update some dependencies, this can be done by executing inside the «/www/pixelfed/pixelfed» directory the following command:
composer update
We will see something like this:
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Package operations: 181 installs, 0 updates, 0 removals
- Downloading aws/aws-crt-php (v1.0.2)
- Downloading dasprid/enum (1.0.3)
- Downloading bacon/bacon-qr-code (2.0.7)
- Downloading symfony/polyfill-mbstring (v1.26.0)
- Downloading symfony/deprecation-contracts (v3.1.1)
- Downloading symfony/http-foundation (v6.1.7)
- Downloading psr/http-message (1.0.1)
We copy the environment variables file:
cp .env.example .env
In this file we can change the variables of the application configuration, for this example we are interested in the following lines:
APP_NAME="Pixelfed"
APP_ENV="production"
APP_KEY= APP_DEBUG="false"
# Instance Configuration
OPEN_REGISTRATION="false"
ENFORCE_EMAIL_VERIFICATION="false"
PF_MAX_USERS="1000"
# Instance URL Configuration
APP_URL="http://pixelfed.int"
APP_DOMAIN="pixelfed.int"
ADMIN_DOMAIN="pixelfed.int"
SESSION_DOMAIN="pixelfed"
# Database Configuration
DB_CONNECTION="mysql"
DB_HOST="127.0.0.1"
DB_PORT="3306"
DB_DATABASE="pixelfed"
DB_USERNAME="pixelfed"
DB_PASSWORD="the_secure_password"
# ActivityPub Configuration ACTIVITY_PUB="true" AP_REMOTE_FOLLOW="true" AP_INBOX="true" AP_OUTBOX="true" AP_SHAREDINBOX="true"
We save and follow up.
Single-step execution
These commands must be executed with the user «pixelfed», inside the «pixelfed» folder:
su -l pixelfed -s /bin/bash; cd ; cd pixelfed
Execute these commands one by one, in case of error it will have to be investigated.
php artisan key:generate
php artisan storage:link
php artisan migrate --force
php artisan import:cities
php artisan instance:actor
php artisan passport:keys
php artisan route:cache
php artisan view:cache
php artisan config:cache
If everything went well and you have no errors, then you can create the service, this should be done as the «root» user.
We will create the file «/etc/systemd/system/pixelfed.service» with the following content:
[Unit]
Description=Pixelfed task queueing via Laravel Horizon
After=network.target
Requires=mariadb
Requires=php-fpm
Requires=redis
Requires=apache
[Service]
Type=simple
ExecStart=/usr/bin/php /www/pixelfed/pixelfed/artisan horizon
User=pixelfed
Restart=on-failure
[Install]
WantedBy=multi-user.target
We enable the service with in the systemd with the following command:
systemctl enable --now pixelfed
Finally as the user «pixelfed», we will create a user and add one in the crontab.
First we add the user by executing the following:
php artisan user:create
We will be asked for some information, such as if we want to make you an administrator and if we want to verify your email manually, we will answer yes to everything:
Creating a new user...
Name:
> Gonzalo
Username:
> goxonline
Email:
> goxonline@somedomain.com
Password:
>*******
Confirm Password:
>*******
Make this user an admin? (yes/no) [no]:
> yes
Manually verify email address? (yes/no) [no]:
> yes
Are you sure you want to create this user? (yes/no) [no]:
> yes
Created new user!
Add the following entry to the crontab by executing «crontab -e»:
* * * * * /usr/bin/php /www/pixelfed/pixelfed/artisan schedule:run >> /dev/null 2>&1
If all goes well, enter your domain in a browser, and you should see this:

And that’s it!
Any problems you encounter, leave me a comment!