Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
deploy_laravel_application_on_a_linux_vds [2025/05/12 12:25] kkaragozdeploy_laravel_application_on_a_linux_vds [2025/05/13 07:48] (current) kkaragoz
Line 95: Line 95:
 </code> </code>
 ===== 3- Bind a Domain ===== ===== 3- Bind a Domain =====
-Connect a domain to a server can be done by simply changing the DNS records of the domain. Lets assume the VDS server's IP address as 100.45.213.77. Here is an example DNS record table:+Connect a domain to a server can be done by simply changing the DNS records of the domain. You will typically manage these records through your **domain registrar's website** or a **separate DNS hosting provider's control panel**. Lets assume the VDS server's IP address as 100.45.213.77. 
 + 
 +Here is an example DNS record table you might configure:
  
 ^ Type ^ Name ^ Content       ^ TTL  ^ ^ Type ^ Name ^ Content       ^ TTL  ^
Line 103: Line 105:
 | AAAA | @    | Public IPv6   | Auto | | AAAA | @    | Public IPv6   | Auto |
  
-  @ stands for the full domain address (FQDN) like ''%%vicky.com%%''+  * ''%%@%%'' stands for the base domain address (often called the root domain or FQDN) like ''%%vicky.com%%''
-  For IPv6 you should create AAAA record. +  For IPv6you should create an AAAA record pointing to your server's public IPv6 address
-  * stands for the whole subdomains like ''%%*.vicky.com%%''+  * ''%%*%%'' stands for a wildcard, representing all subdomains that don't have a specific A record defined, like ''%%anything.vicky.com%%''
-  sub1: I wrote sub1 but it can be anything. I'll assume ''%%secret%%'' instead of ''%%sub1%%'', this record stands for ''%%secret.vicky.com%%''+  * ''%%sub1%%'': I wrote sub1 but it can be anything. I'll assume ''%%secret%%'' instead of ''%%sub1%%'', this record stands for ''%%secret.vicky.com%%''
-  You can add more subdomains as I showed on the table by ''%%sub1%%''+  You can add more specific subdomains as needed by creating additional A records. 
 +  * ''%%TTL%%'' (Time To Live) is the duration that DNS resolvers are told to cache your record before requesting a fresh copy. 'Auto' is usually fine, letting the provider decide. 
 + 
 +{{ :screenshot_20250512_121756.png?400 | Example screenshot of a DNS configuration interface (placeholder)}} 
 + 
 +You don't have to add explicit records for every single subdomain if you use the ''%%*%%'' wildcard record. However, note that an explicit record for a specific subdomain will take precedence over the wildcard record. 
 + 
 +**DNS Propagation:** After saving your DNS changes, it can take some time for these updates to propagate across the internet's DNS servers. This process, called propagation, can range from a few minutes to several hours, sometimes up to 48 hours, though typically faster for A records. You can use online tools or command-line utilities like ''%%dig%%'' or ''%%nslookup%%'' to check the status of your DNS propagation from different locations.
  
-{{ :screenshot_20250512_121756.png?400 |}}+Once these DNS records are pointing to your server's IP address, you will configure your web server (Nginx) in the next section to respond to requests for these domain names.
 ===== 4- Nginx Installation & Configuration ===== ===== 4- Nginx Installation & Configuration =====
 [[https://nginx.org|nginx]] ("engine x") is an HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server. Before nginx installation we should be ensure about apache/apache2 is not running and enabled. [[https://nginx.org|nginx]] ("engine x") is an HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server. Before nginx installation we should be ensure about apache/apache2 is not running and enabled.
Line 236: Line 245:
  
 ===== 5- SSL Certification: Certbot ===== ===== 5- SSL Certification: Certbot =====
-It is time to apply SSL certificates of domainsI use "**Full SSL Encryption**" on CloudFlare for my domain addresses.To install SSL certificates firstly check for updates:+It is essential to secure your application with SSL/TLS encryption to protect data in transit and build user trust. [[https://letsencrypt.org/|Let's Encrypt]] provides free, automated, and open Certificate Authorities, and [[https://certbot.eff.org|Certbot]] is a tool to easily obtain and manage these certificates, especially for web servers like Nginx. 
 + 
 +You mentioned using "**Full SSL Encryption**" on Cloudflare. This means Cloudflare encrypts the connection between the user and Cloudflare, and ''%%also%%'' encrypts the connection between Cloudflare and your origin server. For Cloudflare's "Full SSL" to work correctly, your server ''%%still needs a valid SSL certificate%%''. Certbot will provide this valid certificate. 
 + 
 +To install Certbot and the Nginx plugin, first ensure your package list is up-to-date:
 <code bash> <code bash>
 sudo apt update && sudo apt upgrade sudo apt update && sudo apt upgrade
 </code> </code>
  
-We are ready to install [[https://certbot.eff.org|Certbot]]:+Now we are ready to install Certbot:
 <code bash> <code bash>
 sudo apt install certbot python3-certbot-nginx sudo apt install certbot python3-certbot-nginx
 </code> </code>
  
-After installation is completed, lets move to the ''%%sites-enabled%%'' path again.+After installation is completed, we will use the Certbot Nginx plugin, which can automatically configure SSL for domains specified in your Nginx configuration files located in ''%%/etc/nginx/sites-enabled/%%''. 
 <code bash> <code bash>
-cd /etc/nginx/sites-enabled/+sudo certbot --nginx
 </code> </code>
 +When you run this command, Certbot will:
 +  * Prompt you for an email address for urgent renewal or security notices.
 +  * Ask you to agree to the terms of service.
 +  * Scan your Nginx configuration files for ''%%server_name%%'' directives to find the domains you want to secure.
 +  * Present a list of identified domains and ask you to select which ones you want certificates for.
 +  * Communicate with the Let's Encrypt servers to verify domain ownership (usually by serving a temporary file through your web server).
 +  * If successful, it will obtain the SSL certificates.
 +  * **Automatically modify** your Nginx configuration file(s) in ''%%/etc/nginx/sites-enabled/%%'' to:
 +    * Add the ''%%listen 443 ssl;%%'' directive for HTTPS.
 +    * Point to the correct ''%%ssl_certificate%%'' and ''%%ssl_certificate_key%%'' files it just obtained.
 +    * (Optionally) Ask if you want to redirect HTTP traffic (port 80) to HTTPS (port 443). It is highly recommended to choose the redirect option for better security and SEO.
 +  * **Automatically set up a renewal mechanism** (usually a systemd timer or cron job) that will attempt to renew your certificates before they expire (Let's Encrypt certificates are valid for 90 days).
  
-Then run the following command for automatic SSL certificate process:+After Certbot completes its process and potentially modifies your Nginx configuration, it will usually handle reloading or restarting Nginx itself. However, it's a good practice to test the Nginx configuration and explicitly reload to be sure:
  
 <code bash> <code bash>
-sudo certbot --nginx +sudo nginx -t # Test Nginx configuration for syntax errors 
-</code> +sudo systemctl reload nginx # Reload Nginx to apply changes
-Enter the related fields like email, confirm terms, select domains, etc. Then Certbot will notify about the certification status. If it's done, you can reload the nginx again. +
-<code bash> +
-sudo systemctl reload nginx+
 </code> </code>
  
 +You can verify that SSL is working by visiting your domain(s) in a web browser and checking for the padlock icon in the address bar and ensuring the URL starts with ''%%https://%%''.
 +
 +**Important:** The ''%%certbot --nginx%%'' command only needs to be run the first time to obtain the certificate and configure Nginx. Certbot's automatic renewal process handles keeping your certificates up-to-date in the future.
 ===== 6- PHP Installation ===== ===== 6- PHP Installation =====
 Let's proceed to uninstall the currently installed PHP packages and then install a specific version (like PHP 8.2) cleanly using the Ondřej Surý PPA, which is the recommended way for up-to-date PHP versions on Ubuntu/Debian. Let's proceed to uninstall the currently installed PHP packages and then install a specific version (like PHP 8.2) cleanly using the Ondřej Surý PPA, which is the recommended way for up-to-date PHP versions on Ubuntu/Debian.
Line 493: Line 519:
 </code> </code>
  
-We need to set the [[https://laravel.com/docs/12.x/deployment#directory-permissions|directory permissions]]. If you wonder about the file permissions you can deep dive the [[https://wiki.archlinux.org/title/File_permissions_and_attributes|Arch Linux Wiki Page]] 
 <WRAP center round info 60%> <WRAP center round info 60%>
 Laravel will need to write to the bootstrap/cache and storage directories, so you should ensure the web server process owner has permission to write to these directories. Laravel will need to write to the bootstrap/cache and storage directories, so you should ensure the web server process owner has permission to write to these directories.
 +</WRAP>
 +
 +We need to set the [[https://laravel.com/docs/12.x/deployment#directory-permissions|directory permissions]]. If you wonder about the file permissions you can deep dive the [[https://wiki.archlinux.org/title/File_permissions_and_attributes|Arch Linux Wiki Page]]
 +
 +
 +<WRAP center round alert 60%>
 +The method given below is not a safe approach!
 </WRAP> </WRAP>
  
 <code bash> <code bash>
-sudo chmod -R 755 storage+sudo chmod -R 0777 storage
 </code> </code>
 <code bash> <code bash>
-sudo chmod -R 755 bootstrap/cache+sudo chmod -R 0777 bootstrap/cache 
 +</code> 
 + 
 +Using ''%%chmod -R 0777%%'' is indeed a significant security risk because it grants full read, write, and execute permissions to all users on the system for those directories and everything within them. This means if any other user account on your server were compromised, they could potentially modify or inject malicious files into your application's storage or cache directories. 
 + 
 +==== Laravel - Safer & More Standard Approach ==== 
 + 
 +The goal is to grant write permissions only to the specific user or group that the web server (Nginx/PHP-FPM) runs as, while keeping ownership and primary access with your deployment user. 
 + 
 +On Debian systems, the web server user and group is typically www-data. 
 + 
 +Here's a safer and more standard approach: 
 + 
 +=== Step 1: Ensure Correct Ownership === 
 +First, make sure the entire application directory is owned by your deployment user (vicky) and their primary group (vicky). You already have this step, which is correct: 
 + 
 +<code bash> 
 +sudo chown -R vicky:vicky /var/www/vicky.com/ 
 +</code> 
 + 
 +=== Step 2: Change Group Ownership for Writable Directories === 
 +Change the group ownership of the storage and bootstrap/cache directories (and their contents) to the web server group (www-data). 
 + 
 +<code bash> 
 +sudo chgrp -R www-data /var/www/vicky.com/storage 
 +sudo chgrp -R www-data /var/www/vicky.com/bootstrap/cache 
 +</code> 
 + 
 +=== Step 3: Set Appropriate Permissions === 
 +Now, set the permissions. A common pattern is 775 for directories and 664 for files. 
 +  * 775 for directories means: 
 +    * Owner (vicky): Read, Write, Execute (7) - Can list contents, create/delete files, navigate into. 
 +    * Group (www-data): Read, Write, Execute (7) - Can list contents, create/delete files, navigate into. 
 +    * Others: Read, Execute (5) - Can list contents, navigate into, but cannot write or delete. 
 + 
 + 
 +  * 664 for files means: 
 +     * Owner (vicky): Read, Write (6) - Can read and modify the file. 
 +     * Group (www-data): Read, Write (6) - Can read and modify the file. 
 +     * Others: Read (4) - Can only read the file. 
 + 
 + 
 +You can apply these recursively using find for better control over files vs. directories: 
 + 
 +<code bash> 
 +# Set permissions for directories within storage and bootstrap/cache 
 +sudo find /var/www/vicky.com/storage -type d -exec chmod 775 {} + 
 +sudo find /var/www/vicky.com/bootstrap/cache -type d -exec chmod 775 {} + 
 + 
 +# Set permissions for files within storage and bootstrap/cache 
 +sudo find /var/www/vicky.com/storage -type f -exec chmod 664 {} + 
 +sudo find /var/www/vicky.com/bootstrap/cache -type f -exec chmod 664 {} + 
 +</code> 
 + 
 +Note: You could also do sudo chmod -R 775 /var/www/vicky.com/storage /var/www/vicky.com/bootstrap/cache as a simpler command, but this would also give execute permissions to files, which is usually not necessary and slightly less secure than 664 for files. Using find is more precise. 
 + 
 +=== Step 4: Set SetGID Bit (Recommended) === 
 +To ensure that any new files or directories created within storage and bootstrap/cache by the web server process (running as www-data) automatically inherit the www-data group, you can set the SetGID bit on these directories. 
 + 
 +<code bash> 
 +sudo chmod g+s /var/www/vicky.com/storage 
 +sudo chmod g+s /var/www/vicky.com/bootstrap/cache 
 +</code> 
 + 
 +==== Static App - Appropriate Permissions ==== 
 +Generally do not need to set the same 775 group write permissions or change the group ownership to www-data for your static application's folder. The write operations happen during the deployment process when you, as the deployment user (vicky), build the app locally (or on the server) and copy the output files to the server directory ''%%/var/www/static-page.vicky.com%%''
 + 
 +The goal for static assets is to allow the web server (www-data user) to read and execute/navigate through the directories to find the files, while ensuring your deployment user (vicky) has full control to update the files, and restricting write access for others. 
 + 
 +A standard and safe permission set for static web content folders is: 
 + 
 +**Ownership**: The files and directories should be owned by your deployment user (vicky) and their primary group (vicky). 
 + 
 +<code bash> 
 +sudo chown -R vicky:vicky /var/www/static-page.vicky.com 
 +</code> 
 + 
 +**Permissions**: 
 +  * Directories: 755 (Owner: Read, Write, Execute; Group: Read, Execute; Others: Read, Execute). This allows the owner (vicky) full control and allows the web server user (www-data - which falls under "Others" unless specifically added to vicky's group) to navigate into directories and read their contents. 
 +  * Files: 644 (Owner: Read, Write; Group: Read; Others: Read). This allows the owner (vicky) to read and modify the files and allows the web server user (www-data) to read the files. 
 + 
 +You can set these permissions recursively: 
 + 
 +<code bash> 
 +# Ensure ownership is correct 
 +sudo chown -R vicky:vicky /var/www/static-page.vicky.com 
 + 
 +# Set directory permissions to 755 
 +sudo find /var/www/static-page.vicky.com -type d -exec chmod 755 {} + 
 + 
 +# Set file permissions to 644 
 +sudo find /var/www/static-page.vicky.com -type f -exec chmod 644 {} + 
 +</code> 
 + 
 +A slightly simpler, though less precise, common alternative for static sites is just: 
 + 
 +<code bash> 
 +# Ensure ownership is correct 
 +sudo chown -R vicky:vicky /var/www/static-page.vicky.com 
 + 
 +# Set recursive permissions to 755 (grants execute to files, which is harmless for static assets) 
 +sudo chmod -R 755 /var/www/static-page.vicky.com
 </code> </code>
  
Line 519: Line 652:
 php artisan migrate php artisan migrate
 </code> </code>
- 
Back to top