Are you tired of wasting money on clunky deployment services? Want your app deployed faster than you can say “continuous integration”? Look no further — this guide is your one-way ticket to speedy, cost-effective deployments using Coolify on a VPS. With a little help from LuxVPS and NameCheap, you’ll be up and running without emptying your wallet.
Note: While I use a Laravel app as an example, you can deploy whatever application you prefer. And when it comes to environment variables, don’t worry about checking sensitive info into your repository — you can easily configure them directly within Coolify.
1. Get the Right Tools Without Breaking the Bank
VPS: LuxVPS
I recommend LuxVPS for an affordable, reliable VPS solution. Their monthly pricing is hard to beat if you want performance without a premium price tag. If you want to support me use my link ❤ LINK
Domain: NameCheap
For your domain, NameCheap is the way to go. Their prices are budget-friendly, and setting up DNS is simple. Just create two A records:
One for
@
One for
*
(the wildcard)
Both should point to the IP of your VPS.
If you want to support me use my link ❤ LINK
SSH Access: PuTTY for Windows
If you’re on Windows, I personally rely on PuTTY for SSH access. It’s straightforward and gets you connected without any fuss.
2. Installing Coolify on Your VPS
With your VPS ready, it’s time to install Coolify — your new deployment best friend. Log in to your VPS via SSH (using PuTTY if you’re on Windows) and run:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash
This command pulls down and installs Coolify in a snap. Once it’s done, open your browser and navigate to:
http://your-vps-ip:8000
Register your account and log in. When prompted, choose the “install in localhost” option. Next, go to the sidebar settings and set your Coolify access domain (for example, coolify.yourdomain.com
). Then, in the server settings, update the domain field with your wildcard domain. And just like that, Coolify is set up and ready to rock!
3. Deploying Your App from GitHub
Time to put the “deploy” in “deployment” and get your app live — be it Laravel or any other framework of your choosing.
Step 3.1: Create a New Project & Add a Resource
Log into Coolify:
Head to your Coolify dashboard in your browser.Create a New Project:
Click on “Projects” and then “Add Resource.”
Select Private Repository using the GitHub app integration.
Click on Register New App, then Register Now to authorize Coolify with your GitHub account.
Once logged in, search for and select your repository.
- Configure the Project Settings: A form will appear where you can specify:
The branch to deploy (typically main).
The build pack and the port. For instance, if you’re deploying a Laravel app, change the port to 80 (check out the Coolify docs for Laravel for details).
Tip: You’re not limited to Laravel — deploy what works best for your project!
Step 3.2: Set Up Your nixpacks.toml
File
Inside your repository, create (or update) a nixpacks.toml
file with your build configuration. Below is an example configuration for a Laravel app that uses Nginx, PHP-FPM, and Supervisord. Feel free to adjust it based on your app’s needs:
[phases.setup]
nixPkgs = ["...", "python311Packages.supervisor"]
[phases.build]
cmds = [
"mkdir -p /etc/supervisor/conf.d/",
"cp /assets/worker-*.conf /etc/supervisor/conf.d/",
"cp /assets/supervisord.conf /etc/supervisord.conf",
"chmod +x /assets/start.sh",
"..."
]
[start]
cmd = '/assets/start.sh'
[staticAssets]
"start.sh" = '''
#!/bin/bash
# Transform the nginx configuration
node /assets/scripts/prestart.mjs /assets/nginx.template.conf /etc/nginx.conf
# Start supervisor
supervisord -c /etc/supervisord.conf -n
'''
"supervisord.conf" = '''
[unix_http_server]
file=/assets/supervisor.sock
[supervisord]
logfile=/var/log/supervisord.log
logfile_maxbytes=50MB
logfile_backups=10
loglevel=info
pidfile=/assets/supervisord.pid
nodaemon=false
silent=false
minfds=1024
minprocs=200
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///assets/supervisor.sock
[include]
files = /etc/supervisor/conf.d/*.conf
'''
"worker-nginx.conf" = '''
[program:worker-nginx]
process_name=%(program_name)s_%(process_num)02d
command=nginx -c /etc/nginx.conf
autostart=true
autorestart=true
stdout_logfile=/var/log/worker-nginx.log
stderr_logfile=/var/log/worker-nginx.log
'''
"worker-phpfpm.conf" = '''
[program:worker-phpfpm]
process_name=%(program_name)s_%(process_num)02d
command=php-fpm -y /assets/php-fpm.conf -F
autostart=true
autorestart=true
stdout_logfile=/var/log/worker-phpfpm.log
stderr_logfile=/var/log/worker-phpfpm.log
'''
"worker-laravel.conf" = '''
[program:worker-laravel]
process_name=%(program_name)s_%(process_num)02d
command=bash -c 'exec php /app/artisan queue:work --sleep=3 --tries=3 --max-time=3600'
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
numprocs=12
startsecs=0
stopwaitsecs=3600
stdout_logfile=/var/log/worker-laravel.log
stderr_logfile=/var/log/worker-laravel.log
'''
"php-fpm.conf" = '''
[www]
listen = 127.0.0.1:9000
user = www-data
group = www-data
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 50
pm.min_spare_servers = 4
pm.max_spare_servers = 32
pm.start_servers = 18
clear_env = no
'''
"nginx.template.conf" = '''
user www-data www-data;
worker_processes 5;
daemon off;
worker_rlimit_nofile 8192;
events {
worker_connections 4096; # Default: 1024
}
http {
include $!{nginx}/conf/mime.types;
index index.html index.htm index.php;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx-access.log;
error_log /var/log/nginx-error.log;
sendfile on;
tcp_nopush on;
server_names_hash_bucket_size 128; # this seems to be required for some vhosts
server {
listen ${PORT};
listen [::]:${PORT};
server_name localhost;
$if(NIXPACKS_PHP_ROOT_DIR) (
root ${NIXPACKS_PHP_ROOT_DIR};
) else (
root /app;
)
add_header X-Content-Type-Options "nosniff";
client_max_body_size 35M;
index index.php;
charset utf-8;
$if(NIXPACKS_PHP_FALLBACK_PATH) (
location / {
try_files $uri $uri/ ${NIXPACKS_PHP_FALLBACK_PATH}?$query_string;
}
) else (
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; }
$if(IS_LARAVEL) (
error_page 404 /index.php;
) else ()
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include $!{nginx}/conf/fastcgi_params;
include $!{nginx}/conf/fastcgi.conf;
fastcgi_param PHP_VALUE "upload_max_filesize=30M \n post_max_size=35M";
}
location ~ /\.(?!well-known).* {
deny all;
}
}
}
'''
Step 3.3: Environment Variables
Important: Do not commit your environment variables into your repository. Instead, add them in the Coolify project configuration. This keeps your sensitive data secure and separate from your codebase.
Step 3.4: Final Domain Tweaks
In your project settings within Coolify, update the domain configuration to your production domain. Once set up, every push to your main branch will trigger an automatic deployment. Sit back and watch the magic happen — deployments so fast you might even beat your coffee break!
Final Thoughts
Deploying your app doesn’t have to be expensive or complicated. With LuxVPS keeping costs low, NameCheap securing your domain, and Coolify automating the process, you’re ready to roll out updates faster than ever before. Whether you’re deploying a Laravel app or any other project, this setup is designed to be simple, efficient, and incredibly cost-effective.
Happy coding — and even happier deploying! Remember, every push to your main branch means another set-it-and-forget-it deployment. Enjoy the speed and savings!
Questions? Comments? Drop them below and let’s chat about all things fast, frugal, and full-stack!
Top comments (0)