Installation

Installation

This guide will walk you through installing RadioSaaS on your server. RadioSaaS includes a guided installation wizard that makes setup simple and straightforward.

System Requirements

Server Requirements

  • PHP 8.2+ with required extensions
  • MySQL 5.7+ or MariaDB 10.3+
  • Node.js 18+ and npm for frontend builds
  • Composer 2.x for PHP dependency management

PHP Extensions

Ensure the following PHP extensions are installed:

  • bcmath
  • ctype
  • curl
  • dom
  • fileinfo
  • json
  • mbstring
  • openssl
  • pdo
  • pdo_mysql
  • tokenizer
  • xml

Optional Extensions (Recommended)

  • gd — Image processing for logo/avatar uploads
  • imagick — Advanced image processing (alternative to gd)
  • redis — Redis caching for better performance
  • zip — ZIP file handling

Directory Permissions

The following directories must be writable:

  • storage/
  • bootstrap/cache/

Recommended Hosting

We recommend using a VPS for the best performance. You can get started with $200 free credit on DigitalOcean using our referral link:

DigitalOcean Referral Badge (opens in a new tab)

  • VPS (DigitalOcean, Vultr, Linode, Hetzner)
  • Cloud (AWS, Google Cloud, Azure)
  • Managed Laravel Hosting (Laravel Forge, Ploi)
  • Shared Hosting ⚠️ Not recommended — Multi-tenancy requires wildcard subdomains (*.yourdomain.com), which most shared hosts do not support.

Installation via Wizard (Recommended)

RadioSaaS comes with two main files that are important for the installation process:

  • install.sh — The installation script
  • radiosaas-vX.X.X.zip — The main application files (zipped)

Requirements:

  • Root/Sudo Access: You need root or sudo privileges.
  • SSH Access: Ensure you checked that you can connect to your server via SSH.

The installation script automatically handles the configuration of Nginx and the installation of required dependencies, including MySQL, PHP, and more.

Follow the steps below to install RadioSaaS automatically

RadioSaaS installation involves just two simple steps:

Step 1: Upload Files

Upload all files to your server's web root directory:

# Upload via SFTP, SCP, or your preferred method
# Ensure all files are in your web root (e.g., /root)
# You can use this command to upload files (replace user@your-server with your actual server details and run the command from the directory containing the files):
scp -r install.sh radiosaas-vX.X.X.zip user@your-server:/root

Step 2: Run Installation Script

Required Script Permissions:

Before running the script, ensure it has the correct permissions:

ssh user@your-server 'chmod +x /root/install.sh' 

Running the Installation Script:

# Run the installation script
# Replace user@your-server with your actual server details
# Ensure the path to install.sh is correct and the zip file is in the same directory
ssh user@your-server 'bash /root/install.sh radiosaas-vX.X.X yourdomain.com name db_password' 

The install.sh script requires the following arguments:

  • radiosaas-vX.X.X — The name of the main zip file (without the .zip extension).
  • yourdomain.com — Your actual domain name.
  • name — A name for your instance (used for creating the database and database user).
  • db_password — Your database password (store this securely, as you may need it later).

Usage Example:

ssh root@radiosaas.tech 'bash /root/install.sh radiosaas-v1.0.0 radiosaas.tech radiosaas password'

Note: If you encounter an error, try running the script with sudo (adjust the command based on your server configuration):

sudo bash /root/install.sh radiosaas-v1.0.0 radiosaas.tech radiosaas password

Tadaa! RadioSaaS is installed! 🎉

After the script finishes, you need to verify your license and finalize the setup via the web installer.

You will need the database credentials (name and db_password) you set during the script execution.

Note:

  • Keep the default database host 127.0.0.1 and port 3306.
  • The database username is the same as the name you provided during installation. (For easy setup, we use the same name for both the database and the database user.)

Access Installation Wizard

Navigate to your domain in a web browser:

https://your-domain.com/install

The wizard will guide you through:

  1. Requirements Check - Verifies PHP version, extensions, and permissions
  2. License Verification - Enter your Envato purchase code.

    Important: If you enter the wrong purchase code 5 times, your installation process will be blocked temporarily. This block resets automatically after a timeout, or you can contact our support team for a token to unblock it immediately. Please double-check your code!

  3. Database Configuration - Enter MySQL credentials and test connection
  4. Application Settings - Set site name and URL
  5. Admin Account - Create your administrator account
  6. Installation - Runs migrations, seeds data, and configures the app

Login

After successful installation, you'll be redirected to the admin login page:

https://your-domain.com/admin/login

Login with the admin credentials you created during installation.

Manual Installation (Advanced)

Requirements:

  • Root/Sudo Access: You need root or sudo privileges.
  • SSH Access: Ensure you checked that you can connect to your server via SSH.

1. Update System Packages

First, update and upgrade your system packages to prepare for the installation process.

apt-get update
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"

2. Install Nginx & Required Packages

DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" nginx zip unzip git curl

3. Install PHP & Extensions

add-apt-repository ppa:ondrej/php -y
apt update
DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" php8.3-fpm php8.3-mysql php8.3-mbstring php8.3-xml php8.3-bcmath php8.3-curl php8.3-zip php8.3-intl php8.3-gd

4. Install MySQL

DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" mysql-server

4.1 Configure MySQL

Create the database:

mysql -u root -e "CREATE DATABASE IF NOT EXISTS radiosaas;"

(You can change radiosaas to your preferred database name)

Create the database user:

mysql -u root -e "CREATE USER IF NOT EXISTS 'radiosaas'@'localhost' IDENTIFIED BY 'your_password';"

(Replace your_password with a secure password)

Grant permissions:

mysql -u root -e "GRANT ALL PRIVILEGES ON radiosaas.* TO 'radiosaas'@'localhost';"

5. Upload and Unzip the File

Navigate to the directory where you uploaded the zip file:

unzip -q radiosaas-vX.X.X.zip -d /var/www/html/radiosaas

Navigate to the extracted directory:

cd /var/www/html/radiosaas

6. Configure Environment

# Copy environment file
cp .env.example .env
 
# Generate application key
php artisan key:generate

Edit your .env file:

APP_NAME="RadioSaaS"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com

# Required for multi-tenancy - extract domain from APP_URL
CENTRAL_DOMAIN=your-domain.com

# Database Configuration
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=radiosaas
DB_USERNAME=radiosaas_user
DB_PASSWORD=your_secure_password

# Session & Cache
SESSION_DRIVER=file
CACHE_STORE=file

Update the .env file with the database credentials you created in Step 4.1.

Clear the configuration cache to ensure your changes take effect:

php artisan config:clear

7. Install Dependencies

Note: If you are installing via the zip file, standard dependencies are usually pre-packaged. However, running composer install ensures you have the correct PHP version and optimized class loader map.

composer install --no-dev --optimize-autoloader

(The frontend assets (CSS/JS) are already compiled and included in the zip file, so npm install and npm run build are not required unless you plan to modify the frontend source code.)

8. Run Migrations and Seeders

Run database migrations:

php artisan migrate

Seed the database with required data:

php artisan db:seed

Tip: If you encounter issues, you can reset the database and re-seed (warning: this deletes all data):

php artisan migrate:fresh --seed

9. Build Frontend (Optional)

Since the zip file comes with pre-built assets, you generally do not need to run this. Only run these commands if you are making changes to the Vue/React code:

npm install
npm run build

10. Configure Storage and Permissions

Create the required directories:

mkdir -p storage/framework/{cache,sessions,views}
mkdir -p storage/logs

Set the correct permissions:

chown -R www-data:www-data /var/www/html/radiosaas
chmod -R 775 /var/www/html/radiosaas/storage
chmod -R 775 /var/www/html/radiosaas/bootstrap/cache

Create the storage symlink:

php artisan storage:link

11. Optimize for Production

php artisan optimize
php artisan config:cache
php artisan route:cache
php artisan view:cache
sudo -u www-data php artisan key:generate
sudo -u www-data php artisan storage:link

Web Server Configuration

Nginx Configuration

Create a new Nginx configuration file:

# Open with your preferred text editor (e.g., nano)
nano /etc/nginx/sites-available/your-domain

Configure the file based on your installation path and domain settings:

server {
    listen 80;
    listen [::]:80;
    server_name your-domain.com *.your-domain.com;
    root /var/www/html/your-domain/public;
 
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
 
    index index.php;
    charset utf-8;
 
    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_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
 
        include fastcgi_params;
 
        # Buffer settings (Great for your radio app's API/JSON responses)
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
    }
 
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Enable the site:

sudo ln -s /etc/nginx/sites-available/radiosaas /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Note: The wildcard *.your-domain.com is important for multi-tenancy. Each tenant will have their own subdomain.

Apache Configuration

Create /etc/apache2/sites-available/radiosaas.conf:

<VirtualHost *:80>
    ServerName your-domain.com
    ServerAlias *.your-domain.com
    DocumentRoot /var/www/radiosaas/public
 
    <Directory /var/www/radiosaas/public>
        AllowOverride All
        Require all granted
    </Directory>
 
    ErrorLog ${APACHE_LOG_DIR}/radiosaas_error.log
    CustomLog ${APACHE_LOG_DIR}/radiosaas_access.log combined
</VirtualHost>

Enable the site:

sudo a2ensite radiosaas.conf
sudo a2enmod rewrite
sudo systemctl reload apache2

SSL Certificate

We strongly recommend using HTTPS. Since RadioSaaS uses multi-tenancy with subdomains, you need a Wildcard SSL Certificate (e.g., *.your-domain.com). We will use Let's Encrypt with a DNS challenge to obtain this.

Step 1: Install Certbot

sudo apt install certbot python3-certbot-nginx

Step 2: Request the Wildcard Certificate

Run the following command to request a certificate for both your main domain and the wildcard subdomains:

sudo certbot certonly --manual --preferred-challenges dns -d your-domain.com -d *.your-domain.com

Step 3: Add the DNS TXT Record

Certbot will pause and provide you with a long alphanumeric string. Do not press Enter yet.

  1. Log in to your domain registrar (e.g., Namecheap, GoDaddy, Cloudflare).
  2. Navigate to DNS Settings.
  3. Add a new TXT Record:
    • Type: TXT
    • Host: _acme-challenge

      Warning: Do not enter _acme-challenge.your-domain.com unless your registrar specifically requires the full domain. Most just want the subdomain part (_acme-challenge). entering the full domain might create _acme-challenge.your-domain.com.your-domain.com.

    • Value: (Paste the string provided by Certbot)
    • TTL: Automatic or 1 min (lowest possible).

Step 4: Verify Propagation

Before telling Certbot to continue, verifying that the DNS changes have propagated is crucial.

Open a new terminal window (or use mxtoolbox.com (opens in a new tab)) and run:

dig _acme-challenge.your-domain.com TXT +short
  • If it returns nothing: WAIT. Retrying too soon can cause the challenge to fail.
  • If it returns the correct code: Go back to your Certbot terminal and press Enter.

Step 5: Configure Nginx for SSL

Once the certificate is generated, update your Nginx configuration to use it.

Open your site configuration:

nano /etc/nginx/sites-available/your-domain

Replace the content with the following configuration (update your-domain.com to your actual domain):

server {
    server_name your-domain.com *.your-domain.com;
    root /var/www/html/your-domain/public;
 
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
 
    index index.php;
    charset utf-8;
 
    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_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        
        # Buffer settings
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
    }
 
    location ~ /\.(?!well-known).* {
        deny all;
    }
 
    # SSL Configuration
    listen [::]:443 ssl ipv6only=on; 
    listen 443 ssl; 
    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; 
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; 
    include /etc/letsencrypt/options-ssl-nginx.conf; 
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 
}
 
server {
    listen 80;
    listen [::]:80;
    server_name your-domain.com *.your-domain.com;
 
    # FORCE HTTPS FOR EVERYONE (Main Domain AND Subdomains)
    return 301 https://$host$request_uri;
}

Step 6: Test and Reload Nginx

sudo nginx -t
sudo systemctl reload nginx

Default Admin Credentials

If using the AdminSeeder directly (manual installation):

  • Email: admin@admin.com
  • Password: password

⚠️ Important: Change these credentials immediately after first login!

Troubleshooting

Permission Errors

# Fix storage permissions
sudo chmod -R 775 storage bootstrap/cache
sudo chown -R www-data:www-data storage bootstrap/cache

Database Connection Issues

# Test database connection
php artisan tinker
>>> DB::connection()->getPdo();

Vite Manifest Error

If you see "Unable to locate file in Vite manifest":

npm run build

Installation Keeps Redirecting

If the app keeps redirecting to /install even after installation:

  1. Check if storage/installed file exists
  2. Verify the signature in the file is valid
  3. Ensure APP_KEY hasn't changed since installation

Reset Installation

To reset and reinstall:

# Remove installed marker
rm -f storage/installed
rm -f storage/install_license_tries.json
 
# Reset database
php artisan migrate:fresh
 
# Re-run installation wizard
# Navigate to https://your-domain.com/install

Or use the artisan command:

php artisan license:reset --token=YOUR_RESET_TOKEN

Support

Need help with installation?

  • Review the troubleshooting section above
  • Contact support for installation assistance