This assumes root is logged in via SSH to the latest Ubuntu server, with the root SSH authorized keys stored in /root/authorized_keys
.
Another assumption is that you use postgres and redis hosted on different database servers, so we don't install those on the app server.
Edit the SSH config and disable password login. Update the SSH port to something random.
vim /etc/ssh/sshd_config
systemctl reload sshd
Install nginx and PHP, create a user for deployments.
apt-get upgrade
apt-get update
apt-get install ca-certificates apt-transport-https software-properties-common nginx gnupg supervisor
add-apt-repository ppa:ondrej/php
apt-get update
apt-get install php8.3 php8.3-fpm php8.3-xml php8.3-curl php8.3-mbstring php8.3-zip php8.3-pgsql php8.3-redis php8.3-intl
adduser laravel -G sudo,www-data
mkdir /home/laravel/.ssh
cp ~/.ssh/authorized_keys /home/laravel/.ssh
chown -R laravel:laravel /home/laravel/.ssh
Install nodejs.
mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=20
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
apt-get update
apt-get install nodejs -y
Setup firewall.
ufw app list
ufw allow 'Nginx HTTP'
ufw allow your-ssh-port
ufw enable
Clone your git repo. Fix ownership and permissions.
cd /var/www
rm -rf html
git clone your-repository-url html
chown -R laravel:www-data html
find /var/www/html -type d -print0 | xargs -0 chmod 0775
find /var/www/html -type f -print0 | xargs -0 chmod 0664
Edit /etc/nginx/sites-available/default
and replace its contents with the following after updating the server_name
with your domain. Restart nginx.
server {
listen 80;
listen [::]:80;
server_name example.com;
root /var/www/html/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.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
vim /etc/nginx/sites-available/default
nginx -t
systemctl reload nginx
Create /etc/supervisor/conf.d/horizon.conf
with the following contents and restart supervisor.
[program:horizon]
process_name=%(program_name)s
command=php /var/www/html/artisan horizon
autostart=true
autorestart=true
user=laravel
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/horizon.log
stopwaitsecs=3600
vim /etc/supervisor/conf.d/horizon.conf
supervisorctl reread
supervisorctl update
supervisorctl start horizon
That's it for the root user. From now on, use the laravel
user. Once you are logged in as laravel
, setup cron to run laravel schedule.
You can use crontab -e
to edit the cron.
* * * * * cd /var/www/html && php artisan schedule:run >> /dev/null 2>&1
Every time you need to deploy, you can run these commands
cd /var/www/html
git pull origin main
npm install
find node_modules/.bin/ -type f -exec chmod +x {} \;
npm run build
composer install --optimize-autoloader --no-dev
php artisan config:cache
php artisan event:cache
php artisan route:cache
php artisan view:cache
php artisan migrate --force --isolated
php artisan horizon:terminate