<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrew Quaye</title>
    <description>The latest articles on DEV Community by Andrew Quaye (@iquipe).</description>
    <link>https://dev.to/iquipe</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1792607%2F621223c2-4af8-459f-8017-15ce8256a1ae.png</url>
      <title>DEV Community: Andrew Quaye</title>
      <link>https://dev.to/iquipe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iquipe"/>
    <language>en</language>
    <item>
      <title>How to Set Up Apache Virtual Hosts on an Ubuntu VM</title>
      <dc:creator>Andrew Quaye</dc:creator>
      <pubDate>Mon, 20 Apr 2026 08:07:16 +0000</pubDate>
      <link>https://dev.to/iquipe/how-to-set-up-apache-virtual-hosts-on-an-ubuntu-vm-2h2c</link>
      <guid>https://dev.to/iquipe/how-to-set-up-apache-virtual-hosts-on-an-ubuntu-vm-2h2c</guid>
      <description>&lt;p&gt;Apache Virtual Hosts allow you to host multiple websites or applications on a single server. Each domain or subdomain can point to its own directory, making it possible to run separate projects side by side.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠 Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu VM with sudo access
&lt;/li&gt;
&lt;li&gt;Apache2 installed (&lt;code&gt;sudo apt install apache2 -y&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Domain names pointing to your server’s public IP (configured via DNS)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Create Project Directory
&lt;/h2&gt;

&lt;p&gt;Each site should have its own directory under &lt;code&gt;/var/www/html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example for &lt;code&gt;api.iquipe.cloud&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/html/api
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; www-data:www-data /var/www/html/api
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 755 /var/www/html/api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a test file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;?php phpinfo(); ?&amp;gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /var/www/html/api/index.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Create Virtual Host Configuration
&lt;/h2&gt;

&lt;p&gt;Apache stores site configs in &lt;code&gt;/etc/apache2/sites-available/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a new file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/apache2/sites-available/api-your-domainname-com.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nl"&gt;VirtualHost&lt;/span&gt;&lt;span class="sr"&gt; *:80&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="nc"&gt;ServerName&lt;/span&gt; api-your-domainname.com
    &lt;span class="nc"&gt;DocumentRoot&lt;/span&gt; /var/www/html/api

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nl"&gt;Directory&lt;/span&gt;&lt;span class="sr"&gt; /var/www/html/api&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="nc"&gt;Options&lt;/span&gt; &lt;span class="ss"&gt;FollowSymLinks&lt;/span&gt;
        &lt;span class="nc"&gt;AllowOverride&lt;/span&gt; &lt;span class="ss"&gt;All&lt;/span&gt;
        &lt;span class="nc"&gt;Require&lt;/span&gt; &lt;span class="ss"&gt;all&lt;/span&gt; granted
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nl"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="nc"&gt;ErrorLog&lt;/span&gt; ${APACHE_LOG_DIR}/api_error.log
    &lt;span class="nc"&gt;CustomLog&lt;/span&gt; ${APACHE_LOG_DIR}/api_access.log combined
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nl"&gt;VirtualHost&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Enable the Site
&lt;/h2&gt;

&lt;p&gt;Enable your new Virtual Host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2ensite api-your-domainname-com.conf
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disable the default site if you don’t need it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2dissite 000-default.conf
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Test Access
&lt;/h2&gt;

&lt;p&gt;Visit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api-your-domainname-com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the PHP info page.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Enable SSL (Recommended)
&lt;/h2&gt;

&lt;p&gt;Install Certbot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-apache &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Request a certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--apache&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; api-your-domainname-com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose the redirect option so HTTP traffic is automatically redirected to HTTPS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Manage Multiple Virtual Hosts
&lt;/h2&gt;

&lt;p&gt;Repeat the process for other domains (e.g., &lt;code&gt;test.domainame.com&lt;/code&gt;). Each domain gets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its own directory under &lt;code&gt;/var/www/html/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Its own config file under &lt;code&gt;/etc/apache2/sites-available/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Its own SSL certificate (or a shared multi‑domain certificate)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Conclusion
&lt;/h2&gt;

&lt;p&gt;With Virtual Hosts, you can host multiple independent sites on one Ubuntu VM. Each domain points to its own directory, and Apache handles routing. Adding SSL ensures secure connections for all your hosted applications.&lt;/p&gt;




</description>
      <category>devops</category>
      <category>linux</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Automate DigitalOcean Droplet Creation with PHP (Including Root Password Setup!)</title>
      <dc:creator>Andrew Quaye</dc:creator>
      <pubDate>Wed, 26 Mar 2025 06:50:57 +0000</pubDate>
      <link>https://dev.to/iquipe/automate-digitalocean-droplet-creation-with-php-including-root-password-setup-165a</link>
      <guid>https://dev.to/iquipe/automate-digitalocean-droplet-creation-with-php-including-root-password-setup-165a</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4vpd3amfbsamv3ag73t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx4vpd3amfbsamv3ag73t.png" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ever found yourself repeatedly creating DigitalOcean droplets, setting them up, and wishing there was a faster, more automated way? Well, you're in luck! In this article, we'll dive into how to use the DigitalOcean API and PHP to automate droplet creation, with a crucial focus on securely setting the root password.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Automate?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Automation is key to efficient development and DevOps workflows. By automating droplet creation, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Save time:&lt;/strong&gt; Eliminate manual setup processes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce errors:&lt;/strong&gt; Ensure consistent configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale easily:&lt;/strong&gt; Quickly provision multiple droplets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrate with CI/CD:&lt;/strong&gt; Seamlessly incorporate cloud infrastructure into your pipelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A DigitalOcean account and API token. (Generate one in your DigitalOcean control panel.)&lt;/li&gt;
&lt;li&gt;PHP installed with the cURL extension enabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The PHP Script:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's break down the PHP script that does the magic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="c1"&gt;// DigitalOcean API Token (Replace with your actual token)&lt;/span&gt;
&lt;span class="nv"&gt;$apiToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'YOUR_DIGITALOCEAN_API_TOKEN'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Droplet Configuration&lt;/span&gt;
&lt;span class="nv"&gt;$dropletName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'my-new-droplet'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'nyc3'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Example: New York 3&lt;/span&gt;
&lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'s-1vcpu-1gb'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Example: 1GB RAM, 1 vCPU&lt;/span&gt;
&lt;span class="nv"&gt;$image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ubuntu-20-04-x64'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Example: Ubuntu 20.04&lt;/span&gt;
&lt;span class="nv"&gt;$rootPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'YourSecurePassword123!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Replace with a strong password&lt;/span&gt;

&lt;span class="c1"&gt;// API Endpoint&lt;/span&gt;
&lt;span class="nv"&gt;$apiUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'[https://api.digitalocean.com/v2/droplets](https://api.digitalocean.com/v2/droplets)'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Request Data&lt;/span&gt;
&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$dropletName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'region'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'size'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'image'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'ssh_keys'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="c1"&gt;// Optional: Add SSH keys if desired&lt;/span&gt;
    &lt;span class="s1"&gt;'backups'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'ipv6'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'user_data'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"#cloud-config&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;password: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$rootPassword&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;chpasswd:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  list: |&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    root:"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$rootPassword&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  expire: false"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'private_networking'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'volumes'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'tags'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize cURL&lt;/span&gt;
&lt;span class="nv"&gt;$ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$apiUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Set cURL options&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POSTFIELDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_HTTPHEADER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Authorization: Bearer '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$apiToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Execute the request&lt;/span&gt;
&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Check for errors&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;curl_errno&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'cURL Error: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;curl_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Decode the JSON response&lt;/span&gt;
    &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Handle the response&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'droplet'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Droplet created successfully!'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Droplet ID: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'droplet'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Droplet Name: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'droplet'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Droplet IP: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'droplet'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'networks'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'v4'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'ip_address'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;//It is very important to remove the password after the droplet is created.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Error creating droplet: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Print the error details&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Close cURL&lt;/span&gt;
&lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points and Security Considerations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;user_data&lt;/code&gt; for Root Password:&lt;/strong&gt; The most secure method for setting the root password is by using the &lt;code&gt;user_data&lt;/code&gt; field within the droplet creation request. This leverages cloud-init to configure the droplet upon initialization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Immediate Password Change:&lt;/strong&gt; After creating the droplet, &lt;em&gt;immediately&lt;/em&gt; change the root password or disable password authentication altogether. SSH keys are strongly recommended for secure access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling:&lt;/strong&gt; The script includes robust error handling using &lt;code&gt;curl_errno()&lt;/code&gt; and provides informative error messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration:&lt;/strong&gt; Remember to replace the placeholder values for your API token, droplet name, region, size, image, and password.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH Keys:&lt;/strong&gt; The script includes a placeholder for &lt;code&gt;ssh_keys&lt;/code&gt;. It is strongly recomended to use ssh keys instead of passwords.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to Run the Script:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Save the code as a &lt;code&gt;.php&lt;/code&gt; file (e.g., &lt;code&gt;create_droplet.php&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; Replace the placeholder values with your actual credentials and desired configuration.&lt;/li&gt;
&lt;li&gt; Run the script from your terminal: &lt;code&gt;php create_droplet.php&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Further Enhancements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add SSH key support.&lt;/li&gt;
&lt;li&gt;Implement input validation for user-provided parameters.&lt;/li&gt;
&lt;li&gt;Create a web interface for easier droplet management.&lt;/li&gt;
&lt;li&gt;Integrate with other tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Automating DigitalOcean droplet creation with PHP can significantly streamline your workflow. By following the best practices outlined in this article, you can create droplets quickly and securely. Remember to prioritize security, especially when handling sensitive information like passwords.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
  </channel>
</rss>
