VPS Installation

Install MediaDesk on your own Ubuntu server with nginx, from an empty server to a live site.
Version: 1.2.0
Stack: Laravel 13 · PHP 8.3 · MySQL

Item: MediaDesk — Multilingual AI-Powered Newsroom ERP

Before You Start

This guide installs MediaDesk on a fresh Ubuntu 24.04 server with nginx. You run every command over SSH. On other Linux systems the package names differ, and the steps stay the same.

You needDetails
A VPSAt least 2 GB RAM and 20 GB disk, with a sudo user
A domainAn A record pointing at the server IP. This guide uses news.example.com: replace it with your domain everywhere.
The downloadMediaDesk-Main_Files.zip. You only install WebSourceCode on the server.

No SSH access, only a hosting control panel? Follow the cPanel Installation guide instead.

1. Install the Server Software

sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx mysql-server unzip supervisor redis-server \
  php8.3-fpm php8.3-cli php8.3-mysql php8.3-mbstring php8.3-xml php8.3-curl \
  php8.3-gd php8.3-intl php8.3-zip php8.3-bcmath php8.3-redis composer

# Node.js 20 (Ubuntu's own package is too old)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

Check the versions. You need PHP 8.3 or newer, Composer 2 and Node.js 20 or newer:

php -v && composer --version && node -v

2. Create the Database

Open MySQL with sudo mysql, then run this with your own password:

CREATE DATABASE mediadesk CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mediadesk'@'localhost' IDENTIFIED BY 'a-strong-password';
GRANT ALL PRIVILEGES ON mediadesk.* TO 'mediadesk'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Use this dedicated user, not root. The installer counts every table the user can see, so a user with access to other databases is refused with “already contains tables”, even when the new database is empty.

3. Upload the Files

From your computer, copy the download to the server:

scp MediaDesk-Main_Files.zip [email protected]:~/

On the server, unpack it into the web folder:

unzip -q ~/MediaDesk-Main_Files.zip -d ~/mediadesk-package
sudo mkdir -p /var/www/mediadesk
sudo chown -R $USER:$USER /var/www/mediadesk
cp -a ~/mediadesk-package/Main_Files/WebSourceCode/. /var/www/mediadesk/

4. Install Dependencies and Build

vendor/ and public/build/ are not in the download. These commands create them:

cd /var/www/mediadesk
composer install --no-dev --optimize-autoloader
npm ci
npm run build
rm -rf node_modules

Use composer install. Never run composer update: it changes the tested package versions.

5. Create .env and Set Ownership

Create .env from the example. Leave its values as they are: the installer fills in the site address, database details and security key in step 8.

cd /var/www/mediadesk
cp .env.example .env
sudo chown -R www-data:www-data /var/www/mediadesk
sudo find /var/www/mediadesk -type d -exec chmod 755 {} \;
sudo find /var/www/mediadesk -type f -exec chmod 644 {} \;
sudo chmod 640 .env

Do not skip this. Without a .env file the installer page answers with a 500 error.

6. Configure PHP and nginx

Raise the PHP limits so large media uploads work:

sudo tee /etc/php/8.3/fpm/conf.d/99-mediadesk.ini > /dev/null <<'EOF'
upload_max_filesize = 256M
post_max_size = 256M
memory_limit = 512M
max_execution_time = 300
EOF
sudo systemctl restart php8.3-fpm

Create the site with sudo nano /etc/nginx/sites-available/mediadesk:

server {
    listen 80;
    server_name news.example.com;
    root /var/www/mediadesk/public;
    index index.php;
    charset utf-8;

    client_max_body_size 256M;

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

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_read_timeout 300;
    }

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

Enable it:

sudo ln -s /etc/nginx/sites-available/mediadesk /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

7. Turn On HTTPS

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d news.example.com

Certbot adds the certificate to the nginx site and renews it automatically. Do this before the installer, so that the site address you enter there starts with https://.

8. Run the Installer

Open https://news.example.com. It redirects to the installer.

ScreenWhat to enter
1. RequirementsEvery line must be green. If an extension is red, install its php8.3-… package and restart php8.3-fpm.
2. DatabaseSite name, site URL https://news.example.com, host localhost, port 3306, database mediadesk, username mediadesk and the password from step 2
3. AdministratorYour name, e-mail and a password of at least 8 characters. This is your Super Admin login.
4. DoneThe installer creates the tables and base data, then closes itself for good. Sign in at /login.

9. Add the Scheduler

Scheduled articles, renewals, reminders, digests and social posts all depend on this one line. Open the cron table of the web user:

sudo crontab -u www-data -e

Add:

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

10. Start the Queue Worker

Newsletters, push alerts and social posts are sent by a background worker. First switch the queue to Redis in /var/www/mediadesk/.env:

QUEUE_CONNECTION=redis

Then create the worker with sudo nano /etc/supervisor/conf.d/mediadesk-worker.conf:

[program:mediadesk-worker]
command=php /var/www/mediadesk/artisan queue:work redis --sleep=3 --tries=1 --max-time=3600
user=www-data
numprocs=2
process_name=%(program_name)s_%(process_num)02d
autostart=true
autorestart=true
stopasgroup=true
stopwaitsecs=3600
redirect_stderr=true
stdout_logfile=/var/log/mediadesk-worker.log

Start it:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status

11. Finish and Verify

cd /var/www/mediadesk
sudo -u www-data php artisan optimize
sudo -u www-data php artisan queue:restart
sudo -u www-data php artisan mediadesk:doctor

The doctor lists any problem with its fix. Warnings about AI keys and push keys are optional features, which you can add later.

After this, any edit to .env needs sudo -u www-data php artisan optimize and queue:restart again, or the old values stay in use.

Next: After Installing for your site identity, time zone, mail and payment settings.

If Something Goes Wrong

What you seeFix
500 error on /install.env is missing. Repeat step 5.
“Already contains tables” on an empty databaseThe database user can see other databases. Use the dedicated user from step 2.
500 error on every page, or a Vite manifest errorvendor/ or public/build/ is missing. Repeat step 4, then the chown from step 5.
“Permission denied” in the logRun the chown from step 5 again.
502 Bad GatewayPHP is not running: sudo systemctl restart php8.3-fpm. Check that the socket path in the nginx site matches.
Large uploads failCheck client_max_body_size in nginx and the limits in step 6.
Newsletters stay “sending”The worker is not running: sudo supervisorctl status.

The log is at /var/www/mediadesk/storage/logs/laravel.log. More answers are in the Troubleshooting FAQ.