Assumes Linux env for all parts. Notes are included on:
- Ubuntu (22.04 LTS/24.04 LTS)
- Arch
Locally, consider using Valet Linux. This mostly replaces using serve
, and brings the local environment more in line with a server (uses nginx, php-fpm, etc.)
adduser username
usermod -aG sudo username
apt update
apt upgrade
nano /etc/ssh/sshd_config
PasswordAuthentication yes
temporarily
- Log out
- Locally,
ssh-copy-id username@hostname
- or
ssh-copy-id -i ~/.ssh/KEY -o PubkeyAuthentication=no USERNAME@DOMAIN
- or
- Log in as
username
sudo nano /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
- (DO) May also need:
sudo nano /etc/ssh/sshd_config.d/50-cloud-init.conf
PasswordAuthentication no
- Or
sudo rm /etc/ssh/sshd_config.d/50-cloud-init.conf
if it contains no other settings
sudo systemctl restart ssh
# Ubuntu:
sudo apt install nginx curl wget mariadb-server mariadb-client
# Arch:
sudo pacman -S nginx curl wget mariadb
sudo systemctl status mariadb
sudo systemctl start mariadb # If not already running
sudo systemctl enable mariadb # on Arch
# Additionally, on Arch:
sudo mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
-
sudo mysql_secure_installation
sudo mariadb-secure-installation
on Arch
-
Enter for none
-
DON'T switch to unix_socket authentication
-
DO
- change root password
- remove anon users
- disable root login remotely
- remove test database,
- reload privilege tables
-
sudo mysql -u root -p
-
CREATE DATABASE database_name;
-
GRANT ALL PRIVILEGES ON database_name.* TO 'user'@'localhost' IDENTIFIED BY 'password';
-
FLUSH PRIVILEGES;
-
\q
- Try optimizing memory use first (use nginx, adjust php-fpm config)
- Perform mariaDB setup on a different droplet (1GB recommended)
- !! Works best in the same data center !!
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
bind-address = 0.0.0.0
sudo systemctl restart mysql
sudo ufw allow from SERVER.IP.ADDRESS.HERE to any port 3306
- Create mysql users as
user@server.ip.address
# Ubuntu:
# For current version (8.1 as of 22.04 LTS, 8.3 as of 24.04):
sudo apt install php-fpm php-bcmath php-json php-mbstring php-mysql php-tokenizer php-xml php-zip php-curl php-gd php-intl php-imagick imagemagick
# optional/for dev env, handles code coverage calc: php-pcov
sudo update-alternatives --config php
# can be used if need be to switch PHP version being used. Good esp for dev envs where multiple are present
# Arch:
# Legacy (8.2):
sudo pacman -S php-legacy-fpm php-legacy-gd php-legacy-intl php-imagick imagemagick
sudo nano /etc/php-legacy/php.ini
# Enable bcmath, zip, pdo_mysql, mysqli, gd, intl, curl, iconv
sudo systemctl enable php-legacy-fpm
sudo systemctl start php-legacy-fpm
# Current (8.3):
sudo pacman -S php-fpm php-gd php-intl php-imagick imagemagick
sudo nano /etc/php/php.ini
# Enable bcmath, zip, pdo_mysql, mysqli, gd, intl, curl, iconv
sudo systemctl enable php-fpm
sudo systemctl start php-fpm
- Ubuntu:
sudo apt install composer
- Arch:
sudo pacman -S composer
sudo mkdir /etc/nginx/sites-available
sudo mkdir /etc/nginx/sites-enabled
sudo nano /etc/nginx/nginx.conf
- add
include sites-enabled/*;
to the end of theHTTP
block
sudo systemctl enable nginx
sudo systemctl restart nginx
# Ubuntu:
sudo apt install phpmyadmin
sudo phpenmod mbstring
# Arch:
sudo pacman -S phpmyadmin
link
:- Ubuntu:
/usr/share/phpmyadmin
- Arch:
/usr/share/webapps/phpMyAdmin
- Ubuntu:
sudo nano /etc/nginx/sites-available/mysql.your_domain
- (Server-Specific) Alternately replace
/etc/nginx/sites-available/default
if on a dedicated droplet
Ubuntu:
server {
listen 80;
server_name mysql.your_domain;
root /usr/share/phpmyadmin;
index index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Arch:
server {
server_name mysql.your_domain;
listen 80;
index index.php;
access_log /var/log/nginx/pma.access.log;
error_log /var/log/nginx/pma.error.log;
root /usr/share/webapps/phpMyAdmin;
location / {
try_files $uri $uri/ =404;
}
error_page 404 /index.php;
location ~ \.php$ {
try_files $uri $document_root$fastcgi_script_name =404;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param HTTP_PROXY "";
fastcgi_param HTTPS on;
fastcgi_request_buffering off;
}
}
sudo ln -s /etc/nginx/sites-available/mysql.your_domain /etc/nginx/sites-enabled/
sudo systemctl restart nginx
- (Local) Edit
/etc/hosts
to point at127.0.0.1
and the desired local URL
- Ubuntu:
- Local (if using
serve
):sudo nano /etc/php/8.1/cli/php.ini
- Server:
sudo nano /etc/php/8.1/fpm/php.ini
- Local (if using
- Arch:
- Current:
sudo nano /etc/php/php.ini
- Legacy:
sudo nano /etc/php-legacy/php.ini
- Current:
- Adjust
post_max_size
andupload_max_filesize
as desired - Restart
serve
(local) orsudo systemctl restart php8.1-fpm
(server/vagrant)
# Ubuntu:
sudo nano /etc/php/8.1/fpm/php-fpm.conf
# Substitute with relevant version as necessary
# Arch:
sudo nano /etc/php/php-fpm.conf
emergency_restart_threshold 10
emergency_restart_interval 1m
process_control_timeout 10s
# Ubuntu:
sudo nano /etc/php/8.1/fpm/pool.d/www.conf
# Substitute with relevant version as necessary
# Arch:
sudo nano /etc/php/php-fpm.d/www.conf
For low-traffic sites /shared servers(/multiple php-fpm pools) /situations where memory use must be optimized:
pm = ondemand
pm.max_children = 80
pm.process_idle_timeout = 10s
pm.max_requests = 200
Else use dynamic
and configure to suit traffic needs/memory limitations
sudo systemctl restart php8.1-fpm
sudo nano /etc/nginx/nginx.conf
- Add
client_max_body_size 10M;
(set to desired value) sudo systemctl restart nginx
sudo mkdir /var/www/your_domain
sudo mkdir /var/www/your_domain/www
sudo mkdir /var/www/your_domain/www/public
sudo chown -R $USER:$USER /var/www/your_domain
sudo chmod -R 755 /var/www/your_domain
ln -s /var/www/your_domain /home/$USER/your_domain # For convenience
git config --global --add safe.directory /var/www/your_domain/www
sudo nano /etc/nginx/sites-available/your_domain
Config contents:
server {
server_name your_domain www.your_domain;
root /var/www/your_domain/www/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.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
From https://laravel.com/docs/11.x/deployment#nginx
sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
sudo nginx -t # Test for config errors
sudo service nginx restart
sudo ufw app list # Ensure this contains both nginx and OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw allow 'OpenSSH'
sudo ufw enable
sudo ufw status # Should contain nginx and OpenSSH
sudo apt install fail2ban
sudo systemctl start fail2ban && sudo systemctl enable fail2ban
- At the time of writing, see fail2ban #3487 wrt an issue on Ubuntu 24.04.
sudo fail2ban-client status
to view statussudo fail2ban-client status sshd
to view SSH bans
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx
sudo systemctl status certbot.timer # verify no error/service running
sudo certbot renew --dry-run # can use to test renewal process
# Ubuntu 22.04:
sudo apt install apt-config-auto-update
sudo dpkg -i --force-overwrite /var/cache/apt/archives/apt-config-auto-update_2.1+nmu1_all.deb
# replace with relevant version/archive path
# Ubuntu 24.04:
sudo apt install unattended-upgrades
sudo systemctl enable unattended-upgrades
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
- Uncomment allowed-origins
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::InstallOnShutdown "false";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";
sudo systemctl restart unattended-upgrades
sudo unattended-upgrades
sudo crontab -e
- Add
0 0 * * * /usr/bin/unattended-upgrade -d
- Git should already be installed, if not,
sudo apt install git
- Set the default branch name to main:
git config --global init.defaultBranch main
- Set the default branch name to main:
cd ~/your_domain/www
git init
cd ../ && mkdir site_hub.git && cd site_hub.git
git --bare init
- Push to
ssh://username@hostname/~/your_domain/site_hub.git
cd ../www && git remote add hub ../site_hub.git
git pull hub main
cd .git/hooks && nano post-commit
#!/bin/sh
echo
echo "**** Pushing changes to Hub [Prime's post-commit hook]"
echo
git push hub
chmod +x post-commit
cd ../../../site_hub.git/hooks && nano post-update
#!/bin/sh
echo
echo "**** Pulling changes into Prime [Hub's post-update hook]"
echo
cd $HOME/your_domain/www || exit
unset GIT_DIR
git pull hub main
exec git-update-server-info
chmod +x post-update
crontab -e
- Add
* * * * * cd ~/your_domain/www && php artisan schedule:run >> /dev/null 2>&1
cd ~/your_domain/www # or wherever you have your project
composer install #/ php composer.phar install if using PHP 7.4 on 22.04
php artisan key:generate
php artisan migrate
Fix permissions:
#apache
cd ../ && wget https://gist.githubusercontent.com/itinerare/ca00d05b9c0a43c7763df113623c4f2d/raw/04ca6429f26b8ade656e4a9e559e1b292bd603bb/fixfolderperms.sh && sudo chmod +x fixfolderperms.sh && sudo sh fixfolderperms.sh
#nginx
cd ../ && wget https://gist.githubusercontent.com/itinerare/cbb0cc8b58918908c18959a6f691dff7/raw/3d8d99b7d708c2c163b5cd7502d3f5b2a4367ed4/fixfolderperms.sh && sudo chmod +x fixfolderperms.sh && sudo sh fixfolderperms.sh
# may also need to refer to https://stackoverflow.com/a/37266353
composer create-project laravel/laravel project-name