Skip to content

Deployment

The following configuration ensures optimal Nginx performance. Ensure that URLs are properly configured in the .env file according to your nginx nameservers.

Copy the /app directory to /var/www/html on the target server for installation.

Import Database

Use phpMyAdmin or a MySQL management tool such as HeidiSQL to import /app/database/pressify-v1.0.sql into the database configured in your .env file with the corresponding authentication credentials.

Using Command Line

bash
php artisan pressify:dbinit

Default Administrator Account

Manual Installation

Schedule CronJob

Configure a CronJob on the server to ensure scheduled post publishing, sitemap generation, traffic synchronization, and real-time traffic broadcasting.

bash
* * * * * root cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1

Customize the schedule in /app/routes/console.php

Supervisord Configuration

You can set up automatic process management through Supervisord using the following configuration:

bash
[program:pressify-horizon]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan horizon
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=root
numprocs=1
redirect_stderr=true
stdout_logfile=/var/log/supervisor/pressify-horizon.log
stopwaitsecs=3600

[program:pressify-reverb]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan reverb:start
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=root
numprocs=1
redirect_stderr=true
stdout_logfile=/var/log/supervisor/pressify-reverb.log
stopwaitsecs=3600

[program:pressify-queue-scout]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work database --queue=scout
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=root
numprocs=1
redirect_stderr=true
stdout_logfile=/var/log/supervisor/pressify-queue-scout.log
stopwaitsecs=3600

Or run manually:

  • Execute php /var/www/html/artisan horizon
  • Execute php /var/www/html/artisan reverb:start to start the socket server for displaying real-time post traffic analytics.
  • Execute php /var/www/html/artisan queue:work database --queue=scout for indexing posts into Typesense

Scout Index

Execute php artisan scout:import "App\Models\Post" to index posts into Typesense.

Warm Post Cache

Execute php artisan cache:warm-post to regenerate the cache for all posts currently in the database. This command only needs to be run once during initial setup.

Nginx Configuration

Refer to the pre-configured settings in /.docker-php/8.3/rootfs/etc/nginx

Backend

nginx
server {
    listen [::]:80;
    listen 80;
    server_name cms.pressify.local; # Admin URL

    sendfile off;
    tcp_nodelay on;
    absolute_redirect off;

    root /var/www/html/public;
    index index.php index.html;
    autoindex off;

    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$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php8.4-fpm.sock; # Replace with your PHP version
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_index index.php;

        include fastcgi_params;
    }

    location ~ /\. {
        log_not_found off;
        deny all;
    }
}

Frontend

nginx
server {
    listen [::]:80;
    listen 80;
    server_name pressify.local;

    sendfile off;
    tcp_nodelay on;
    absolute_redirect off;

    root /var/www/html/public;
    index index.php index.html;
    autoindex off;

    # Handle /video path - prevent directory listing but allow file access
    location ~ ^/video/?$ {
        rewrite ^ /index.php?$query_string last;
    }

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

    error_page 404 /index.php;

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php8.4-fpm.sock; # Replace with your PHP version
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    location ~ /\. {
        log_not_found off;
        deny all;
    }

    # Ensure nginx image filter module is installed
    # Add the configuration below if you have not configured a separate CDN URL
    location /thumb {
        alias /var/www/html/public/resize;
        set $width 0;
        set $height 0;
        set $dimens "";
        if ($uri ~* "^/thumb_x(\d*)x(\d*)/(.*)" ) {
            set $width $1;
            set $height $2;
            set $image_path $3;
            set $demins "_$1x$2";
            set $image_uri image_resize/$image_path?width=$width&height=$height;
        }
        if ($uri ~* "^/thumb_xx(\d*)/(.*)" ) {
            set $width 10000;
            set $height $1;
            set $image_path $2;
            set $demins "_xx$1";
            set $image_uri image_resize/$image_path?width=$width&height=$height;
        }
        if ($uri ~* "^/thumb_x(\d*)x/(.*)" ) {
            set $width $1;
            set $height 10000;
            set $image_path $2;
            set $demins "_$1xx";
            set $image_uri image_rs/$image_path?width=$width&height=$height;
        }

        if (!-f $request_filename) {
            proxy_pass http://127.0.0.1/$image_uri;
            break;
        }
        proxy_store /var/cache/nginx/pressify/resize$demins/$image_path;
        proxy_store_access user:rw group:rw all:r;
        proxy_set_header Host $host;
        allow all;
    }

    location /image_resize {
        alias /var/www/html/public/;
        image_filter crop $arg_width $arg_height;
        image_filter_buffer 5M;
        image_filter_jpeg_quality 85;
        allow all;
    }

    location /image_rs {
        alias /var/www/html/public/;
        image_filter resize $arg_width $arg_height;
        image_filter_buffer 10M;
        image_filter_jpeg_quality 90;
        allow all;
        expires 2d;
        add_header Cache-Control public;
    }
}

CDN

For automatic image resizing and cropping via URL, install the nginx-mod-http-image-filter module for Nginx.

Images
nginx

server {
    listen [::]:80;
    listen 80;
    server_name img.pressify.local;

    sendfile off;
    tcp_nodelay on;
    absolute_redirect off;

    root /var/www/html/public/media/;
    index index.php index.html;
    autoindex off;

    location ~ /\. {
        log_not_found off;
        deny all;
    }

    location /thumb {
        alias /var/www/html/public/resize;
        set $width 0;
        set $height 0;
        set $dimens "";
        if ($uri ~* "^/thumb_x(\d*)x(\d*)/(.*)" ) {
            set $width $1;
            set $height $2;
            set $image_path $3;
            set $demins "_$1x$2";
            set $image_uri image_resize/$image_path?width=$width&height=$height;
        }
        if ($uri ~* "^/thumb_xx(\d*)/(.*)" ) {
            set $width 10000;
            set $height $1;
            set $image_path $2;
            set $demins "_xx$1";
            set $image_uri image_resize/$image_path?width=$width&height=$height;
        }
        if ($uri ~* "^/thumb_x(\d*)x/(.*)" ) {
            set $width $1;
            set $height 10000;
            set $image_path $2;
            set $demins "_$1xx";
            set $image_uri image_rs/$image_path?width=$width&height=$height;
        }

        if (!-f $request_filename) {
            proxy_pass http://127.0.0.1/$image_uri;
            break;
        }

        proxy_store /var/cache/nginx/pressify/resize$demins/$image_path;
        proxy_store_access user:rw group:rw all:r;
        proxy_set_header Host $host;
        allow all;
    }

    location /image_resize {
        alias /var/www/html/public/media/;
        image_filter crop $arg_width $arg_height;
        image_filter_buffer 5M;
        image_filter_jpeg_quality 95;
        allow all;
    }

    location /image_rs {
        alias /var/www/html/public/media/;
        image_filter resize $arg_width $arg_height;
        image_filter_buffer 10M;
        image_filter_jpeg_quality 100;
        allow all;
        expires 2d;
        add_header Cache-Control public;
    }
}
Videos
nginx
server {
    listen [::]:80;
    listen 80;
    server_name video.pressify.local;

    sendfile off;
    tcp_nodelay on;
    absolute_redirect off;

    root /var/www/html/public/video/;
    index index.php index.html;
    autoindex off;
}
Audios
nginx
server {
    listen [::]:80;
    listen 80;
    server_name audio.pressify.local;

    sendfile off;
    tcp_nodelay on;
    absolute_redirect off;

    root /var/www/html/public/audio/;
    index index.php index.html;
    autoindex off;
}
Files
nginx
server {
    listen [::]:80;
    listen 80;
    server_name file.pressify.local;

    sendfile off;
    tcp_nodelay on;
    absolute_redirect off;

    root /var/www/html/public/file/;
    index index.php index.html;
    autoindex off;
}
Socket (Reverb)

Reverb starts on the default port 6001.

nginx
server {
    listen [::]:80;
    listen 80;
    server_name socket.pressify.local;

    location / {
        proxy_pass http://127.0.0.1:6001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 60s;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

FastCGI Configuration

Refer to the pre-configured settings in /.docker-php/8.3/rootfs/etc/nginx

Docker Installation

Update the nginx configuration in /home/tsspress/.docker-php/8.3/rootfs/etc/nginx/conf.d/tsspress.conf:

Start the Containers

bash
docker-compose --env-file=./app/.env up -d --build

Initialize Sample Database

bash
docker exec -it pressify-app sh
php artisan pressify:dbinit

Scout Index

Execute php artisan scout:import "App\Models\Post" to index posts into Typesense.

Configure Host File

Add the following entries to your Windows hosts file (C:\Windows\System32\drivers\etc\hosts):

If running Docker on WSL with Docker Desktop, use 127.0.0.1. Otherwise, replace 127.0.0.1 with your WSL IP address (find it using ip addr show eth0 in WSL).

bash
127.0.0.1 pressify.local
127.0.0.1 cms.pressify.local
127.0.0.1 img.pressify.local
127.0.0.1 video.pressify.local
127.0.0.1 audio.pressify.local
127.0.0.1 file.pressify.local
127.0.0.1 socket.pressify.local

Released under the MIT License.