Make sure you have all prerequisites installed and the appropriate services running/enabled before continuing.


Pixelfed is still a work in progress. We do not recommend running an instance in production at this stage unless you know what you are doing!

Setting up Pixelfed files [link]

Download source via Git [link]

Pixelfed Beta currently uses the dev branch for deployable code. When v1.0 is released, the stable branch will be changed to stable, with dev branch being used for development and testing.

cd /usr/share/webapps # or wherever you choose to install web applications
git clone -b dev pixelfed # checkout dev branch into "pixelfed" folder

Set correct permissions [link]

Your web server and app processes need to be able to write to the Pixelfed directory. Make sure to set the appropriate permissions. For example, if you are running your processes through the http user/group, then run the following:

cd pixelfed
sudo chown -R http:http . # change user/group to http user and http group
sudo find . -type d -exec chmod 755 {} \; # set all directories to rwx by user/group
sudo find . -type f -exec chmod 644 {} \; # set all files to rw by user/group

User and group permissions

Make sure to use the correct user/group name for your system. This may be http, www-data, or pixelfed (if using a dedicated user).

Initialize PHP dependencies [link]

Run composer install to fetch the dependencies needed by Pixelfed. It is recommended to run with the following flags:

composer install --no-ansi --no-interaction --optimize-autoloader

Configure environment variables [link]

By default Pixelfed comes with a .env.example file for production deployments, and a .env.testing file for debug deployments. You’ll need to rename or copy one of these files to .env regardless of which environment you’re working on.

cp .env.example .env # for production deployments
cp .env.testing .env # for debug deployments

You can now edit .env and change values for your setup.

List of environment variables

You can find a list of additional configuration settings in-depth on the Configuration page, but the important variables will be listed in the below subsections.

App variables [link]

  • Set APP_NAME to your desired title, e.g. Pixelfed. This will be shown in the header bar and other places.
  • Ensure that APP_DEBUG is false for production environments, or true for debug environments.
  • Set your APP_URL to the HTTPS URL that you wish to serve Pixelfed through, e.g. https://pixelfed.example
  • Set APP_DOMAIN, ADMIN_DOMAIN, and SESSION_DOMAIN to the domain name you will be using for Pixelfed, e.g. pixelfed.example

Database variables [link]

By default, the values provided will allow connecting to MySQL or MariaDB over the default localhost TCP connection.

If you are running Postgres:

  • Set DB_CONNECTION to pgsql instead of mysql.

If you are running your SQL server on a different machine or port:

  • Set DB_HOST to the IP of the machine
  • Set DB_PORT to the port on which your database server is exposed

Alternatively, if you are using a Unix socket:

  • Set DB_SOCKET to the path of the socket, e.g. /run/mysqld/mysqld.sock

To connect to the database you created:

  • Set DB_DATABASE to the name of the database created for Pixelfed
  • Set DB_USERNAME to the user that was granted privileges for that database
  • Set DB_PASSWORD to the password that identifies the user with privileges to the database

Redis variables [link]

If you are running Redis over TCP on the same machine as Pixelfed, then the default settings will work.

If you are running Redis on another machine:

  • Set REDIS_HOST to the IP of the machine your Redis server is running on
  • Set REDIS_PORT to the port on which Redis is exposed
  • Set REDIS_PASSWORD to the password of that Redis server

If you are using a Unix socket for Redis, then:

  • Set REDIS_SCHEME to unix
  • Set REDIS_HOST to the path of the socket, e.g. /run/redis/redis.sock
  • Set REDIS_PORT to 0

TCP server vs. Unix socket

Redis usually comes pre-configured to listen for TCP requests on the local machine over port 6379. In your Redis configuration, typically at /etc/redis.conf, the relevant lines are bind and port 6379.

Changing the latter line to port 0 will disable TCP listening, in which case Redis must be configured for socket access. Lines such as unixsocket /run/redis/redis.sock and unixsocketperm 770 must be set to enable socket access. Additionally, both the app user and web user should have permission to access the socket, e.g. by being added to the redis group.

Using a Unix socket is optional, but may provide faster access since it does not have to create TCP packets. TCP is usually used over a network, and would be required if Redis were running on a different machine than your web server.

Email variables [link]

By default, Pixelfed will not send any emails, but will instead write messages to the Laravel log.

To setup a mailer for production deployments, you have several options for supported mail services. Pixelfed currently supports SMTP, Mailgun, Postmark, Amazon SES, and sendmail for sending emails to users.

  • Set MAIL_FROM_ADDRESS to the email address you want to send from
  • Set MAIL_FROM_NAME to the name you want to appear on emails
  • Set MAIL_ENCRYPTION to tls in order to have emails be properly delivered

SMTP (Mailtrap) [link]

Set up your SMTP server. Or, create an account with Mailtrap.

  • Set MAIL_DRIVER to smtp
  • Set MAIL_HOST to your host, e.g.
  • Set MAIL_PORT to your port, e.g. 587 or 2525
  • Set MAIL_USERNAME and MAIL_PASSWORD if your SMTP server requires authorization. ( does not.)

Mailgun [link]

Create an account with Mailgun.

  • Set MAIL_DRIVER to mailgun
  • Set MAIL_HOST to
  • Set MAIL_PORT to 587
  • Set MAIL_USERNAME to your Mailgun domain
  • Set MAIL_PASSWORD to your Mailgun API key

If you are not using the “US” Mailgun region, you may define your region’s endpoint in the services.php configuration file located in the config/ directory:

'mailgun' => [
    'domain' => env('MAILGUN_DOMAIN'),
    'secret' => env('MAILGUN_SECRET'),
    'endpoint' => '',

Postmark [link]

To use the Postmark driver, install Postmark’s SwiftMailer transport via Composer:

composer require wildbit/swiftmailer-postmark

Next, install Guzzle and set the driver option in your config/mail.php configuration file to postmark. Finally, verify that your config/services.php configuration file contains the following options:

'postmark' => [
    'token' => 'your-postmark-token',

Amazon SES [link]

Create an account with Amazon AWS.

  • Set MAIL_DRIVER to ses
  • Set SES_KEY
  • Set SES_REGION (if not using the default of us-east-1)

sendmail [link]

  • Set MAIL_DRIVER to sendmail

Additional variables [link]

If you are using ImageMagick, then:

  • Set IMAGE_DRIVER to imagick

If you want to enable ActivityPub federation:

  • Set ACTIVITY_PUB to true
  • Set AP_REMOTE_FOLLOW to true

If you want to enable OAuth support for external clients:

  • Set OAUTH_ENABLED to true

Setting up services [link]

One-time setup tasks [link]

One time only, you need to generate the secret APP_KEY:

php artisan key:generate

One time only, the storage/ directory must be linked to the application:

php artisan storage:link

Database migrations must be run:

php artisan migrate --force

If you want to enable support for location data:

php artisan import:cities

If you enabled ActivityPub federation:

php artisan instance:actor

If you enabled OAuth:

php artisan passport:keys

Routes should be cached whenever the source code changes or whenever you change routes:

php artisan route:cache
php artisan view:cache

Every time you edit your .env file, you must run this command to have the changes take effect:

php artisan config:cache

Running Pixelfed without a cache

It is possible to not use a cache by not running the above cache commands, but it is recommended to run these for production deployments. If you choose not to run these commands, then you can freely edit the .env file and source code instead, and your changes will be reflected instantly, but performance may take a slight hit. You can also undo these commands by running :clear commands:

php artisan route:clear
php artisan view:clear
php artisan config:clear

Job queueing [link]

Pixelfed supports both Laravel Horizon and Queue Workers to power the job queue. The main difference between Horizon and Queue Worker is the dashboard provided by Horizon as well as advanced load balancing. We recommend using Horizon. Horizon provides a beautiful dashboard which allows you to easily monitor key metrics of your queue system such as job throughput, runtime, and job failures.

Using Laravel Horizon [link]

If you want admins to be able to access the Horizon web dashboard, you will need to run the following commands:

php artisan horizon:install
php artisan horizon:publish

If your user has the correct permissions to access Redis and the Pixelfed installation folder, then you can simply run php artisan horizon as that user in a terminal. This may be fine, but if you close the terminal then Horizon will also be terminated. Running directly is recommended only in deployments where a terminal can run uninterrupted, e.g. in a VM or using a utility such as GNU Screen or tmux.

If you are running in production, it is more ideal to create a background service for running Pixelfed’s task queue. You will need to use a task manager like systemd or Supervisor. For more information, refer to the Laravel Documentation.

Most distributions will already come with systemd, so you may set up this unit file at /etc/systemd/system/pixelfed.service:

Description=Pixelfed task queueing via Laravel Horizon

ExecStart=/usr/bin/php /usr/share/webapps/pixelfed/artisan horizon


Using correct paths and service names

The example above assumes you are using MariaDB and Nginx, that your distribution’s PHP packages do not have versioned names, and that your distribution uses the http user to serve Nginx. It also assumes that you have installed Pixelfed in /usr/share/webapps/pixelfed in accordance with the rest of the installation process documentation. Some changes you may need to make include:

  • Replacing mariadb with postgresql or mysql
  • Replacing php-fpm with your distro’s PHP-FPM package name, e.g. php8.1-fpm
  • Replacing nginx with apache, or replacing Requires with Wants if you are not running in a production environment
  • Replacing /usr/bin/php or /usr/share/webapps/pixelfed/artisan with the correct paths, e.g. /usr/bin/php8.1 or /path/to/pixelfed/artisan
  • Replacing User=http to reflect the app user, e.g. User=pixelfed or commenting this line in order to run in the system slice.

You can now use systemd to manage Pixelfed like any other background service:

sudo systemctl enable --now pixelfed

Alternatively, if you do not wish to use systemd, then you can install Supervisor and create this sample Supervisor configuration file at /etc/supervisor/conf.d/pixelfed.conf, making sure to use the correct path to your Pixelfed installation and the appropriate app-user:

command=/usr/bin/php /usr/share/webapps/pixelfed/artisan horizon

Using correct paths

You may need to replace /usr/bin/php or /usr/share/webapps/pixelfed/artisan with the correct paths, e.g. /usr/bin/php8.1 or /path/to/pixelfed/artisan

You will then need to run these commands:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start pixelfed

Using Queue Worker [link]

Pixelfed also includes a queue worker that will process new jobs as they are pushed onto the queue. You may run the worker using the queue:work command. Note that once the command has started, it will continue to run until it is manually stopped or you close your terminal:

php artisan queue:work

Again, you can use Supervisor or systemd as described above, substituting horizon for queue:work.

Scheduling periodic tasks [link]

The task scheduler is used to run periodic commands in the background, such as media optimization, garbage collection, and other time-based tasks that should be run every once in a while.

To set up scheduled tasks using Cron:

EDITOR=nano crontab -e

Paste the following cronjob into your crontab:

* * * * * /usr/bin/php /usr/share/webapps/pixelfed/artisan schedule:run >> /dev/null 2>&1

Using correct paths

You may need to replace /usr/bin/php or /usr/share/webapps/pixelfed/artisan with the correct paths, e.g. /usr/bin/php7.3 or /path/to/pixelfed/artisan

Handling web requests [link]

To translate HTTPS web requests to PHP workers, you will need to configure a reverse proxy.

Apache [link]

Pixelfed includes a public/.htaccess file that is used to provide URLs without the index.php front controller in the path. Before serving Pixelfed with Apache, be sure to enable the mod_rewrite module in your Apache configuration so the .htaccess file will be honored by the server.

If the .htaccess file that ships with Pixelfed does not work with your Apache installation, try this alternative:

Options +FollowSymLinks -Indexes
RewriteEngine On

RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

Nginx [link]

Pixelfed includes a sample NGINX configuration at contrib/nginx.conf. You can copy the contents of this file or include it within your nginx.conf. Take note of the comments, and make sure to set the correct domain name and root path.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name pixelfed.example;                    # change this to your fqdn
    root /usr/share/webapps/pixelfed/public;         # path to repo/public

    ssl_certificate /etc/nginx/ssl/server.crt;       # generate your own
    ssl_certificate_key /etc/nginx/ssl/server.key;   # or use letsencrypt

    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;
    client_max_body_size 15M;   # or your desired limit

    location / {
        try_files $uri $uri/ /index.php?$query_string;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php-fpm/php-fpm.sock; # make sure this is correct
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # or $request_filename

    location ~ /\.(?!well-known).* {
        deny all;

server {                                             # Redirect http to https
    server_name pixelfed.example;                    # change this to your fqdn
    listen 80;
    listen [::]:80;
    return 301 https://$host$request_uri;

FastCGI path

Make sure to use the correct fastcgi_pass socket path for your distribution and version of PHP-FPM. For example, on Arch, this is /run/php-fpm/php-fpm.sock, but on Ubuntu it may be /run/php/php8.1-fpm.sock, on Debian it may be /var/run/php/php8.1-fpm.sock, and so on. If you have configured a PHP server over TCP, you may also pass to its IP and port, e.g. localhost:9000 by default.

Nginx web root

Make sure to use the /public folder as your server root. For example:

server {
    root /var/www/pixelfed/public;

If you set root to the install directory (example: root /var/www/pixelfed;) Pixelfed will not work.

Nginx client max body size

Make sure to set an appropriate client_max_body_size setting in the nginx.conf file. Set this slightly greater than your desired post size limit for file uploads. The nginx.conf file location will vary based on your server. /etc/nginx/nginx.conf

Example:http {client_max_body_size 9m;}

Obtaining an HTTPS certificate [link]

For testing deployments, you may generate a self-signed SSL certificate. For example:

sudo mkdir /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt

For production deployments, you will need to obtain a certificate from a certificate authority. You may automate certification from LetsEncrypt, a free certificate authority, by using a utility such as EFF Certbot or

Sample usage of certbot:

certbot --nginx -d pixelfed.example