<?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: Anass Assim</title>
    <description>The latest articles on DEV Community by Anass Assim (@ciscoanass).</description>
    <link>https://dev.to/ciscoanass</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2232387%2F25fbac9b-03ce-45ac-893e-5a418ee95e49.jpg</url>
      <title>DEV Community: Anass Assim</title>
      <link>https://dev.to/ciscoanass</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ciscoanass"/>
    <language>en</language>
    <item>
      <title>Kryptor: Simple File Encryption on Linux</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Sun, 11 Oct 2026 11:16:17 +0000</pubDate>
      <link>https://dev.to/ciscoanass/kryptor-simple-file-encryption-on-linux-3j90</link>
      <guid>https://dev.to/ciscoanass/kryptor-simple-file-encryption-on-linux-3j90</guid>
      <description>&lt;p&gt;Kryptor is a free, open-source command-line tool for encrypting single files (PDFs, images, documents, anything). It uses modern cryptography (XChaCha20-Poly1305 and Argon2id) and has no settings to misconfigure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://www.kryptor.co.uk/" rel="noopener noreferrer"&gt;https://www.kryptor.co.uk/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source: &lt;a href="https://github.com/samuel-lucas6/Kryptor" rel="noopener noreferrer"&gt;https://github.com/samuel-lucas6/Kryptor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Realeses: &lt;a href="https://github.com/samuel-lucas6/Kryptor/releases" rel="noopener noreferrer"&gt;https://github.com/samuel-lucas6/Kryptor/releases&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Privacy : &lt;a href="https://privacytools.io/app/kryptor" rel="noopener noreferrer"&gt;https://privacytools.io/app/kryptor&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Kryptor has not had a public security audit. For extremely sensitive data, consider an audited tool such as VeraCrypt or Cryptomator.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Installation (Ubuntu / Debian / other Linux)
&lt;/h2&gt;

&lt;p&gt;Kryptor is &lt;strong&gt;not&lt;/strong&gt; in the apt repositories, so &lt;code&gt;sudo apt install kryptor&lt;/code&gt; will fail. Install it manually:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Download
&lt;/h3&gt;

&lt;p&gt;Go to the releases page and download the latest Linux x64 zip (for example &lt;code&gt;kryptor-linux-x64.zip&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/samuel-lucas6/Kryptor/releases" rel="noopener noreferrer"&gt;https://github.com/samuel-lucas6/Kryptor/releases&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The release page also lists checksums and signatures if you want to verify the download.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Extract and install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Downloads
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;unzip          &lt;span class="c"&gt;# only if unzip is missing&lt;/span&gt;
unzip kryptor-linux-x64.zip
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x kryptor
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;kryptor /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the extracted file has a different name, rename it to &lt;code&gt;kryptor&lt;/code&gt; when moving it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Check it works
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kryptor &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Encrypt a file with a passphrase
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kryptor &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; report.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be asked to enter a passphrase. The result is a new file, &lt;code&gt;report.pdf.bin&lt;/code&gt;. The original file is &lt;strong&gt;kept&lt;/strong&gt;, so delete it yourself if you no longer want the unencrypted copy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decrypt a file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kryptor &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; report.pdf.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the same passphrase and the original file is restored.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encrypt several files or a folder
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kryptor &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; file1.pdf file2.jpg MyFolder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Quick reference
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Encrypt with passphrase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kryptor -e -p file&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decrypt with passphrase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kryptor -d -p file.bin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Show all options&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kryptor --help&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Option names and output file extensions can differ between versions, so check &lt;code&gt;kryptor --help&lt;/code&gt; if something does not match.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important: why &lt;code&gt;-p&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Without &lt;code&gt;-p&lt;/code&gt;, &lt;code&gt;kryptor -e file&lt;/code&gt; uses &lt;strong&gt;public-key encryption&lt;/strong&gt; and needs a key pair, giving this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: You don't have a default key pair. You can generate one using -g|--generate.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For simple passphrase-based encryption, always add &lt;code&gt;-p&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security tips
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use a strong passphrase.&lt;/strong&gt; 5 to 6 random words is a good target. The passphrase matters more than the algorithm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There is no recovery.&lt;/strong&gt; If you forget the passphrase, the file cannot be decrypted. Store the passphrase in a password manager.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test decryption&lt;/strong&gt; before deleting the original file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete the unencrypted original&lt;/strong&gt; once you are sure the encrypted copy works. Note that a normal delete does not guarantee the data cannot be recovered from the disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep backups&lt;/strong&gt; of your encrypted files.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Alternative: GnuPG (preinstalled on most Linux systems)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Encrypt&lt;/span&gt;
gpg &lt;span class="nt"&gt;--symmetric&lt;/span&gt; &lt;span class="nt"&gt;--cipher-algo&lt;/span&gt; AES256 report.pdf

&lt;span class="c"&gt;# Decrypt&lt;/span&gt;
gpg &lt;span class="nt"&gt;--decrypt&lt;/span&gt; report.pdf.gpg &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; report.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>cli</category>
      <category>linux</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>Pi-hole Setup Guide: Block Ads on Your Laptop, Phone and PC</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Sun, 11 Oct 2026 10:48:04 +0000</pubDate>
      <link>https://dev.to/ciscoanass/pi-hole-setup-guide-block-ads-on-your-laptop-phone-and-pc-bep</link>
      <guid>https://dev.to/ciscoanass/pi-hole-setup-guide-block-ads-on-your-laptop-phone-and-pc-bep</guid>
      <description>&lt;p&gt;A complete, beginner-friendly guide to running &lt;a href="https://pi-hole.net/" rel="noopener noreferrer"&gt;Pi-hole&lt;/a&gt; with Docker, connecting your devices to it, testing that it works, fixing common problems, and moving it to a Raspberry Pi later.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pi-hole is a network-wide ad and tracker blocker. It acts as your DNS server and refuses to resolve the domains that serve ads, so blocking works on every device that uses it, with nothing to install on those devices.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;How it works&lt;/li&gt;
&lt;li&gt;What you need&lt;/li&gt;
&lt;li&gt;Quick start&lt;/li&gt;
&lt;li&gt;Part 1: Install Pi-hole with Docker&lt;/li&gt;
&lt;li&gt;Part 2: Open the dashboard and verify&lt;/li&gt;
&lt;li&gt;Part 3: Find the Pi-hole IP address&lt;/li&gt;
&lt;li&gt;Part 4: Connect your devices&lt;/li&gt;
&lt;li&gt;Part 5: Test that it works&lt;/li&gt;
&lt;li&gt;Troubleshooting&lt;/li&gt;
&lt;li&gt;Daily use and maintenance&lt;/li&gt;
&lt;li&gt;Moving to a Raspberry Pi&lt;/li&gt;
&lt;li&gt;Blocking ads outside your home&lt;/li&gt;
&lt;li&gt;Security notes&lt;/li&gt;
&lt;li&gt;Limitations&lt;/li&gt;
&lt;li&gt;FAQ&lt;/li&gt;
&lt;li&gt;Uninstall / undo everything&lt;/li&gt;
&lt;li&gt;Useful links&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Every time a device opens a website, it first asks a &lt;strong&gt;DNS server&lt;/strong&gt; to turn the name (like &lt;code&gt;example.com&lt;/code&gt;) into an IP address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Without Pi-hole:   Device  -&amp;gt;  Router DNS / ISP DNS  -&amp;gt;  ad domains resolve normally

With Pi-hole:      Device  -&amp;gt;  Pi-hole  -&amp;gt;  ad domain?  YES -&amp;gt; answers 0.0.0.0 (blocked)
                                                         NO  -&amp;gt; forwards to upstream DNS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because blocking happens at the DNS level:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It works on phones, laptops, smart TVs and any other device that uses Pi-hole as its DNS server.&lt;/li&gt;
&lt;li&gt;Nothing is installed on those devices.&lt;/li&gt;
&lt;li&gt;It blocks &lt;strong&gt;domains&lt;/strong&gt;, not individual ads. See Limitations.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A computer to run Pi-hole&lt;/td&gt;
&lt;td&gt;Laptop for testing, or a Raspberry Pi / mini PC / old PC for permanent use. It must stay &lt;strong&gt;on&lt;/strong&gt; for blocking to work.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/get-started/get-docker/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Docker Desktop on Windows and macOS, Docker Engine on Linux.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A home network&lt;/td&gt;
&lt;td&gt;All devices on the &lt;strong&gt;same Wi-Fi / router&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router access (optional)&lt;/td&gt;
&lt;td&gt;Only needed to cover every device automatically (see Moving to a Raspberry Pi).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;For people in a hurry. Details are in the parts below.&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="c"&gt;# 1. Start Pi-hole (one line)&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; pihole &lt;span class="nt"&gt;-p&lt;/span&gt; 53:53/tcp &lt;span class="nt"&gt;-p&lt;/span&gt; 53:53/udp &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80/tcp &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;FTLCONF_webserver_api_password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;change-me &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;FTLCONF_dns_listeningMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;all &lt;span class="nt"&gt;-v&lt;/span&gt; pihole:/etc/pihole &lt;span class="nt"&gt;--restart&lt;/span&gt; unless-stopped pihole/pihole:latest

&lt;span class="c"&gt;# 2. Open the dashboard&lt;/span&gt;
&lt;span class="c"&gt;#    http://localhost:8080/admin&lt;/span&gt;

&lt;span class="c"&gt;# 3. Find the host IP (example: 192.168.1.70), then set it as the&lt;/span&gt;
&lt;span class="c"&gt;#    DNS server on every device you want to protect.&lt;/span&gt;

&lt;span class="c"&gt;# 4. Test&lt;/span&gt;
dig @&amp;lt;PIHOLE_IP&amp;gt; doubleclick.net      &lt;span class="c"&gt;# should return 0.0.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 1: Install Pi-hole with Docker
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 Install Docker
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows / macOS:&lt;/strong&gt; install &lt;a href="https://www.docker.com/products/docker-desktop/" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt;, start it, and wait until it says it is running.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux (Debian/Ubuntu):&lt;/strong&gt; follow the official guide: &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/install/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check that Docker works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Linux you may need &lt;code&gt;sudo&lt;/code&gt; before &lt;code&gt;docker&lt;/code&gt; commands, or add your user to the &lt;code&gt;docker&lt;/code&gt; group.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 Start Pi-hole
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Option A: one command (simplest)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run it as &lt;strong&gt;one line&lt;/strong&gt;. Replace &lt;code&gt;change-me&lt;/code&gt; with your own password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; pihole &lt;span class="nt"&gt;-p&lt;/span&gt; 53:53/tcp &lt;span class="nt"&gt;-p&lt;/span&gt; 53:53/udp &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80/tcp &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;FTLCONF_webserver_api_password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;change-me &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;FTLCONF_dns_listeningMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;all &lt;span class="nt"&gt;-v&lt;/span&gt; pihole:/etc/pihole &lt;span class="nt"&gt;--restart&lt;/span&gt; unless-stopped pihole/pihole:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What each part does:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run in the background&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--name pihole&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name of the container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p 53:53/tcp -p 53:53/udp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;DNS port (needed so other devices can reach Pi-hole)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p 8080:80/tcp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Web dashboard on port 8080 (avoids conflicts with other web servers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FTLCONF_webserver_api_password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dashboard password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FTLCONF_dns_listeningMode=all&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lets Pi-hole answer devices on your network when running in Docker's default bridge mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-v pihole:/etc/pihole&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Saves settings and lists in a Docker volume so they survive updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--restart unless-stopped&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Starts Pi-hole again after a reboot&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Option B: Docker Compose (recommended for a permanent setup)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pihole&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pihole&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pihole/pihole:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;53:53/tcp"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;53:53/udp"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:80/tcp"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;TZ&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Etc/UTC"&lt;/span&gt;                          &lt;span class="c1"&gt;# change to your timezone, e.g. Europe/Paris&lt;/span&gt;
      &lt;span class="na"&gt;FTLCONF_webserver_api_password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;change-me"&lt;/span&gt;
      &lt;span class="na"&gt;FTLCONF_dns_listeningMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./etc-pihole:/etc/pihole"&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.3 Check that it is running
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a container named &lt;code&gt;pihole&lt;/code&gt; with status &lt;code&gt;Up ... (healthy)&lt;/code&gt; and ports &lt;code&gt;53&lt;/code&gt; and &lt;code&gt;8080&lt;/code&gt; listed.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.4 Linux: "port 53 already in use"
&lt;/h3&gt;

&lt;p&gt;On some Linux systems (notably Ubuntu), &lt;code&gt;systemd-resolved&lt;/code&gt; already listens on port 53. If Docker fails to start with an error about port 53:&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; /etc/systemd/resolved.conf.d
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"[Resolve]&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;DNSStubListener=no&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/systemd/resolved.conf.d/pihole.conf
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart systemd-resolved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then start the Pi-hole container again. (Debian with NetworkManager usually does not have this problem.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Open the dashboard and verify
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open a browser on the same computer and go to:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   http://localhost:8080/admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Log in with the password you chose.&lt;/li&gt;
&lt;li&gt;You should see the dashboard with &lt;strong&gt;Status: Active&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point the counters will show &lt;strong&gt;0 queries&lt;/strong&gt;. That is normal: no device is using Pi-hole yet.&lt;/p&gt;

&lt;p&gt;Check that blocking works by asking Pi-hole directly. Replace &lt;code&gt;&amp;lt;PIHOLE_IP&amp;gt;&lt;/code&gt; with the IP address from Part 3 (or use &lt;code&gt;127.0.0.1&lt;/code&gt; on the Pi-hole computer itself):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @&amp;lt;PIHOLE_IP&amp;gt; doubleclick.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer section should contain &lt;code&gt;0.0.0.0&lt;/code&gt;. This means the domain is blocked.&lt;/p&gt;

&lt;p&gt;On Windows, use &lt;code&gt;nslookup&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;nslookup doubleclick.net &amp;lt;PIHOLE_IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get the &lt;code&gt;0.0.0.0&lt;/code&gt; answer, &lt;strong&gt;Pi-hole itself works&lt;/strong&gt;. The rest of this guide is about making your devices actually use it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3: Find the Pi-hole IP address
&lt;/h2&gt;

&lt;p&gt;Devices need the &lt;strong&gt;local IP address&lt;/strong&gt; of the computer running Pi-hole. In this guide it is written as &lt;code&gt;&amp;lt;PIHOLE_IP&amp;gt;&lt;/code&gt; (for example &lt;code&gt;192.168.1.70&lt;/code&gt;).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Look for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ipconfig&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;IPv4 Address (Wi-Fi or Ethernet adapter)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ipconfig getifaddr en0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The address printed (use &lt;code&gt;en1&lt;/code&gt; if &lt;code&gt;en0&lt;/code&gt; is empty)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ip a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;inet 192.168.x.x&lt;/code&gt; on your Wi-Fi or Ethernet interface&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; home IP addresses usually change over time (DHCP). If the IP changes, devices pointing to the old one lose DNS. Give the Pi-hole computer a &lt;strong&gt;fixed IP&lt;/strong&gt; with a &lt;em&gt;DHCP reservation&lt;/em&gt; in your router settings (look for "DHCP reservation", "Address reservation" or "Static lease").&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Part 4: Connect your devices
&lt;/h2&gt;

&lt;p&gt;Two approaches:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Covers&lt;/th&gt;
&lt;th&gt;Effort&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;A. Per device&lt;/strong&gt; (this part)&lt;/td&gt;
&lt;td&gt;Only the devices you configure&lt;/td&gt;
&lt;td&gt;Good for testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;B. On the router&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every device on your network&lt;/td&gt;
&lt;td&gt;See Moving to a Raspberry Pi
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Make sure each device is on the &lt;strong&gt;same Wi-Fi&lt;/strong&gt; as the Pi-hole computer.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 The Pi-hole computer itself (Linux with NetworkManager)
&lt;/h3&gt;

&lt;p&gt;Show the active connections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmcli connection show &lt;span class="nt"&gt;--active&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the DNS (replace &lt;code&gt;YOUR_WIFI_NAME&lt;/code&gt; with the connection name):&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;nmcli connection modify &lt;span class="s2"&gt;"YOUR_WIFI_NAME"&lt;/span&gt; ipv4.ignore-auto-dns &lt;span class="nb"&gt;yes &lt;/span&gt;ipv4.dns &amp;lt;PIHOLE_IP&amp;gt; ipv6.ignore-auto-dns &lt;span class="nb"&gt;yes
sudo &lt;/span&gt;nmcli connection up &lt;span class="s2"&gt;"YOUR_WIFI_NAME"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&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;cat&lt;/span&gt; /etc/resolv.conf
dig doubleclick.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;resolv.conf&lt;/code&gt; should show &lt;code&gt;nameserver &amp;lt;PIHOLE_IP&amp;gt;&lt;/code&gt; and &lt;code&gt;dig&lt;/code&gt; should report &lt;code&gt;SERVER: &amp;lt;PIHOLE_IP&amp;gt;#53&lt;/code&gt; and answer &lt;code&gt;0.0.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you skip this step, the computer running Pi-hole keeps using the router's DNS and its own browser will not be protected, even though Pi-hole works for other devices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4.2 Windows
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Settings -&amp;gt; &lt;strong&gt;Network &amp;amp; internet&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Wi-Fi&lt;/strong&gt; -&amp;gt; click your network&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS server assignment&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Edit&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Manual&lt;/strong&gt;, switch &lt;strong&gt;IPv4&lt;/strong&gt; on&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preferred DNS:&lt;/strong&gt; &lt;code&gt;&amp;lt;PIHOLE_IP&amp;gt;&lt;/code&gt; (leave the alternate empty)&lt;/li&gt;
&lt;li&gt;Save, then open a terminal and run:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;p&gt;If Windows Firewall asks about Docker on the Pi-hole computer, allow it on &lt;strong&gt;private networks&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 macOS
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;System Settings -&amp;gt; &lt;strong&gt;Network&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Wi-Fi&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Details...&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS&lt;/strong&gt; tab -&amp;gt; click &lt;strong&gt;+&lt;/strong&gt; and add &lt;code&gt;&amp;lt;PIHOLE_IP&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remove other DNS servers from the list&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OK&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4.4 Android
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Settings -&amp;gt; &lt;strong&gt;Network &amp;amp; internet&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Wi-Fi&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Long-press your network -&amp;gt; &lt;strong&gt;Modify network&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Advanced options&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP settings:&lt;/strong&gt; &lt;code&gt;Static&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Keep the existing IP address, gateway and prefix length the same&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS 1:&lt;/strong&gt; &lt;code&gt;&amp;lt;PIHOLE_IP&amp;gt;&lt;/code&gt; and clear DNS 2&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then &lt;strong&gt;turn off Private DNS&lt;/strong&gt;, which would bypass Pi-hole:&lt;/p&gt;

&lt;p&gt;Settings -&amp;gt; &lt;strong&gt;Network &amp;amp; internet&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Private DNS&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Off&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(The exact menu names vary by phone brand.)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Setting a static IP on Android can be fiddly. If you prefer, set the DNS on the router instead (see Moving to a Raspberry Pi).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4.5 iPhone / iPad
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Settings -&amp;gt; &lt;strong&gt;Wi-Fi&lt;/strong&gt; -&amp;gt; tap the &lt;strong&gt;(i)&lt;/strong&gt; next to your network&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure DNS&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Manual&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Delete the existing servers and &lt;strong&gt;Add Server:&lt;/strong&gt; &lt;code&gt;&amp;lt;PIHOLE_IP&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Save&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;On the same screen, turn &lt;strong&gt;off&lt;/strong&gt; &lt;em&gt;Limit IP Address Tracking&lt;/em&gt; (iCloud Private Relay) for this network. Private Relay bypasses your DNS.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4.6 Disable browser "secure DNS" (important)
&lt;/h3&gt;

&lt;p&gt;Browsers can send DNS through their own encrypted resolver, skipping Pi-hole completely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Firefox:&lt;/strong&gt; Settings -&amp;gt; &lt;strong&gt;Privacy &amp;amp; Security&lt;/strong&gt; -&amp;gt; &lt;strong&gt;DNS over HTTPS&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Off&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome / Edge / Brave:&lt;/strong&gt; Settings -&amp;gt; &lt;strong&gt;Privacy and security&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Security&lt;/strong&gt; -&amp;gt; turn off &lt;strong&gt;Use secure DNS&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also turn off any &lt;strong&gt;VPN&lt;/strong&gt; while testing, because VPNs usually use their own DNS.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.7 IPv6 note
&lt;/h3&gt;

&lt;p&gt;If your router also advertises an IPv6 DNS server, some devices will use it instead of Pi-hole. If you see ads still loading or devices missing from the Query Log, try disabling IPv6 on that device's Wi-Fi connection while testing, or ignore automatic IPv6 DNS as in the Linux command above.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 5: Test that it works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1 Check the dashboard
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;http://&amp;lt;PIHOLE_IP&amp;gt;:8080/admin&lt;/code&gt; (or &lt;code&gt;http://localhost:8080/admin&lt;/code&gt; on the Pi-hole computer) and browse some websites on your devices.&lt;/p&gt;

&lt;p&gt;You should see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total Queries&lt;/strong&gt; going up&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queries Blocked&lt;/strong&gt; greater than 0 (typically 10-30% on a normal day)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active clients&lt;/strong&gt; increasing as you connect more devices&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.2 Check which devices are connected
&lt;/h3&gt;

&lt;p&gt;Dashboard -&amp;gt; &lt;strong&gt;Query Log&lt;/strong&gt;. The &lt;em&gt;client&lt;/em&gt; column shows the IP of each device that is using Pi-hole:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your phone and PC appear as &lt;code&gt;192.168.x.x&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The Pi-hole computer's own queries may appear as &lt;code&gt;172.17.0.1&lt;/code&gt;. That is Docker's internal address and is normal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.3 See what was blocked
&lt;/h3&gt;

&lt;p&gt;Click &lt;strong&gt;List blocked queries&lt;/strong&gt; on the dashboard to see exactly which domains were stopped.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.4 Test from each device
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;From a PC (Windows, macOS, Linux):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nslookup doubleclick.net &amp;lt;PIHOLE_IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer should be &lt;code&gt;0.0.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From a phone:&lt;/strong&gt; open this in the phone browser while on the same Wi-Fi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://&amp;lt;PIHOLE_IP&amp;gt;:8080/admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the dashboard opens, the phone can reach Pi-hole, so any remaining problem is the phone's DNS setting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Quick diagnosis
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard shows 0 queries&lt;/td&gt;
&lt;td&gt;No device uses Pi-hole yet&lt;/td&gt;
&lt;td&gt;Set DNS on the devices (Part 4), including the Pi-hole computer itself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;dig&lt;/code&gt; shows &lt;code&gt;SERVER: 192.168.1.1&lt;/code&gt; (your router)&lt;/td&gt;
&lt;td&gt;The device still uses the router's DNS&lt;/td&gt;
&lt;td&gt;Redo the DNS setting for that device and reconnect Wi-Fi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;dig @&amp;lt;PIHOLE_IP&amp;gt; doubleclick.net&lt;/code&gt; does not return &lt;code&gt;0.0.0.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Pi-hole problem&lt;/td&gt;
&lt;td&gt;Check &lt;code&gt;docker ps&lt;/code&gt; and &lt;code&gt;docker logs pihole&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No internet after changing DNS&lt;/td&gt;
&lt;td&gt;Pi-hole unreachable (Docker stopped, computer asleep, firewall, wrong IP)&lt;/td&gt;
&lt;td&gt;Set DNS back to automatic, then check the items in this table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phone or PC cannot open &lt;code&gt;http://&amp;lt;PIHOLE_IP&amp;gt;:8080/admin&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Router isolation, different network, or firewall&lt;/td&gt;
&lt;td&gt;See Router isolation and Firewall
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard works but a device is missing in Query Log&lt;/td&gt;
&lt;td&gt;Device bypasses your DNS&lt;/td&gt;
&lt;td&gt;Disable Private DNS / Private Relay / browser secure DNS / VPN / IPv6 DNS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;It worked, then stopped&lt;/td&gt;
&lt;td&gt;The Pi-hole computer's IP changed or it went to sleep&lt;/td&gt;
&lt;td&gt;Check the IP again, set a DHCP reservation, disable sleep&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Some ads still show&lt;/td&gt;
&lt;td&gt;Normal DNS-level limitation&lt;/td&gt;
&lt;td&gt;See Limitations
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error: port 53 already in use&lt;/td&gt;
&lt;td&gt;Another service uses port 53&lt;/td&gt;
&lt;td&gt;See 1.4
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Router isolation
&lt;/h3&gt;

&lt;p&gt;If devices cannot reach the Pi-hole computer at all (the dashboard does not open from the phone or PC):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to your router (often &lt;code&gt;http://192.168.1.1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Look for &lt;strong&gt;AP Isolation&lt;/strong&gt;, &lt;strong&gt;Client Isolation&lt;/strong&gt; or &lt;strong&gt;Guest network&lt;/strong&gt; and turn isolation &lt;strong&gt;off&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Make sure all devices are on the &lt;strong&gt;same&lt;/strong&gt; Wi-Fi network (not a guest network, not mobile data).&lt;/li&gt;
&lt;li&gt;Reconnect the devices and test again.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Firewall
&lt;/h3&gt;

&lt;p&gt;On the Pi-hole computer, make sure ports &lt;strong&gt;53 (TCP and UDP)&lt;/strong&gt; and &lt;strong&gt;8080 (TCP)&lt;/strong&gt; are reachable from your local network.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows:&lt;/strong&gt; allow Docker on &lt;em&gt;private networks&lt;/em&gt; when prompted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux with ufw:&lt;/strong&gt; check with &lt;code&gt;sudo ufw status&lt;/code&gt;. If it says &lt;code&gt;inactive&lt;/code&gt;, it is not blocking anything and you can leave it off. If you use it, the correct commands are:
&lt;/li&gt;
&lt;/ul&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;ufw allow from 192.168.1.0/24 to any port 53
  &lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow from 192.168.1.0/24 to any port 8080 proto tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;192.168.1.0/24&lt;/code&gt; with your own network range.&lt;/p&gt;

&lt;h3&gt;
  
  
  See whether DNS packets reach the computer (advanced)
&lt;/h3&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;tcpdump
&lt;span class="nb"&gt;sudo &lt;/span&gt;tcpdump &lt;span class="nt"&gt;-ni&lt;/span&gt; &amp;lt;INTERFACE&amp;gt; udp port 53 and host &amp;lt;DEVICE_IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Browse on the device:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Packets appear:&lt;/strong&gt; the network path works, so check the Query Log.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing appears:&lt;/strong&gt; the device is not sending DNS to Pi-hole. Check its DNS settings, Private DNS / Private Relay, VPN, or router isolation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Useful diagnostic commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps                       &lt;span class="c"&gt;# is the container running and healthy?&lt;/span&gt;
docker logs pihole              &lt;span class="c"&gt;# Pi-hole logs&lt;/span&gt;
docker restart pihole           &lt;span class="c"&gt;# restart Pi-hole&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/resolv.conf            &lt;span class="c"&gt;# Linux: which DNS does this computer use?&lt;/span&gt;
dig doubleclick.net             &lt;span class="c"&gt;# which server answered, and is it 0.0.0.0?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Daily use and maintenance
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Update Pi-hole (Docker)
&lt;/h3&gt;

&lt;p&gt;Settings are stored in the volume, so updating does not lose them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull pihole/pihole:latest
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; pihole
&lt;span class="c"&gt;# run the same "docker run ..." command from Part 1 again&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Docker Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose pull
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Change the dashboard password
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; pihole pihole setpassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(On a Raspberry Pi installed without Docker: &lt;code&gt;sudo pihole setpassword&lt;/code&gt;.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the blocklists
&lt;/h3&gt;

&lt;p&gt;Dashboard -&amp;gt; &lt;strong&gt;Tools&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Update Gravity&lt;/strong&gt;, or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;pihole pihole &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add more blocklists
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Dashboard -&amp;gt; &lt;strong&gt;Lists&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Paste the list URL into the address field and click &lt;strong&gt;Add&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;strong&gt;Update Gravity&lt;/strong&gt; (Tools menu)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Start with a few well-maintained lists, for example from &lt;a href="https://firebog.net/" rel="noopener noreferrer"&gt;The Firebog&lt;/a&gt; (the green "tick" lists are the safest). Adding too many aggressive lists breaks websites.&lt;/p&gt;

&lt;h3&gt;
  
  
  A website is broken (allow a domain)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Dashboard -&amp;gt; &lt;strong&gt;Query Log&lt;/strong&gt; and find the blocked domain&lt;/li&gt;
&lt;li&gt;Add it to the allow list, or go to &lt;strong&gt;Domains&lt;/strong&gt; and add it as an allowed domain&lt;/li&gt;
&lt;li&gt;Reload the site&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also pause blocking temporarily with &lt;strong&gt;Disable Blocking&lt;/strong&gt; in the menu.&lt;/p&gt;

&lt;h3&gt;
  
  
  Back up your settings
&lt;/h3&gt;

&lt;p&gt;Dashboard -&amp;gt; &lt;strong&gt;Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Teleporter&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Export&lt;/strong&gt;. Keep the file somewhere safe. You can import it on a new Pi-hole (for example after moving to a Raspberry Pi).&lt;/p&gt;

&lt;h3&gt;
  
  
  Common commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop pihole              &lt;span class="c"&gt;# stop&lt;/span&gt;
docker start pihole             &lt;span class="c"&gt;# start&lt;/span&gt;
docker restart pihole           &lt;span class="c"&gt;# restart&lt;/span&gt;
docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; pihole           &lt;span class="c"&gt;# follow the logs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Moving to a Raspberry Pi
&lt;/h2&gt;

&lt;p&gt;A laptop only blocks ads while it is on. A Raspberry Pi (or any always-on device) is better for permanent use.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Prepare the Raspberry Pi
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;strong&gt;Raspberry Pi OS Lite&lt;/strong&gt; with the &lt;a href="https://www.raspberrypi.com/software/" rel="noopener noreferrer"&gt;Raspberry Pi Imager&lt;/a&gt; (enable SSH in the settings).&lt;/li&gt;
&lt;li&gt;Connect it to your router with an &lt;strong&gt;Ethernet cable&lt;/strong&gt; if possible.&lt;/li&gt;
&lt;li&gt;In your router, create a &lt;strong&gt;DHCP reservation&lt;/strong&gt; so the Pi always gets the same IP (for example &lt;code&gt;192.168.1.50&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Install Pi-hole
&lt;/h3&gt;

&lt;p&gt;Either use the same Docker commands as in this guide (install Docker first), or use the official installer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://install.pi-hole.net | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the wizard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick an upstream DNS provider (Cloudflare, Quad9, etc.)&lt;/li&gt;
&lt;li&gt;Keep the default blocklist&lt;/li&gt;
&lt;li&gt;Keep the web admin interface enabled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set the dashboard password:&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;pihole setpassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dashboard is then at &lt;code&gt;http://&amp;lt;PI_IP&amp;gt;/admin&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cover every device: set DNS on the router
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log in to your router.&lt;/li&gt;
&lt;li&gt;Find the &lt;strong&gt;DHCP&lt;/strong&gt; or &lt;strong&gt;LAN&lt;/strong&gt; settings with a &lt;strong&gt;DNS server&lt;/strong&gt; field.&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;primary DNS&lt;/strong&gt; to the Pi's IP (for example &lt;code&gt;192.168.1.50&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave the secondary DNS empty.&lt;/strong&gt; If you add a public DNS as a backup, devices may use it and skip Pi-hole.&lt;/li&gt;
&lt;li&gt;Save, then reconnect your devices (turn Wi-Fi off and on).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every device that gets its settings automatically from the router now uses Pi-hole, and you can set your phone and PC back to &lt;strong&gt;Automatic&lt;/strong&gt; DNS.&lt;/p&gt;

&lt;p&gt;If your router does not allow changing DNS, you can use Pi-hole's built-in DHCP server instead: disable DHCP on the router and enable it in Pi-hole (Settings -&amp;gt; DHCP). Only do this if you understand the change, because two DHCP servers on one network cause problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Import your settings (optional)
&lt;/h3&gt;

&lt;p&gt;Export a Teleporter backup from the old Pi-hole and import it on the new one: &lt;strong&gt;Settings -&amp;gt; Teleporter&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Blocking ads outside your home
&lt;/h2&gt;

&lt;p&gt;When your phone uses mobile data or another Wi-Fi, it does not talk to the Pi-hole at home. To keep the protection, connect to your home network through a VPN:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://tailscale.com/" rel="noopener noreferrer"&gt;Tailscale&lt;/a&gt;&lt;/strong&gt; is the easiest option:

&lt;ol&gt;
&lt;li&gt;Install Tailscale on the Pi-hole computer and on your phone.&lt;/li&gt;
&lt;li&gt;In the Tailscale admin console go to &lt;strong&gt;DNS&lt;/strong&gt; and add the Pi-hole's Tailscale IP as a &lt;strong&gt;custom nameserver&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Override local DNS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Make sure Pi-hole answers Tailscale clients (in Docker you already set &lt;code&gt;FTLCONF_dns_listeningMode=all&lt;/code&gt;; on a bare-metal install set &lt;strong&gt;Settings -&amp;gt; DNS -&amp;gt; Permit all origins&lt;/strong&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WireGuard&lt;/strong&gt; (for example with &lt;a href="https://pivpn.io/" rel="noopener noreferrer"&gt;PiVPN&lt;/a&gt;) is a self-hosted alternative.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do &lt;strong&gt;not&lt;/strong&gt; make Pi-hole reachable directly from the internet (see below).&lt;/p&gt;




&lt;h2&gt;
  
  
  Security notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never port-forward port 53 (or the dashboard) to the internet.&lt;/strong&gt; An open DNS server can be abused in attacks. Use a VPN instead.&lt;/li&gt;
&lt;li&gt;Use a &lt;strong&gt;strong dashboard password&lt;/strong&gt; and do not keep the example password from this guide.&lt;/li&gt;
&lt;li&gt;Keep the container image &lt;strong&gt;updated&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The dashboard on port 8080 uses plain HTTP and is meant for your &lt;strong&gt;home network only&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pi-hole sees the domains your devices request. Keep its logs private and use the &lt;strong&gt;Privacy&lt;/strong&gt; settings (Settings -&amp;gt; Privacy) to reduce what is stored.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;Pi-hole is excellent, but it is not magic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It blocks &lt;strong&gt;domains&lt;/strong&gt;. Ads served from the same domain as the content (for example most &lt;strong&gt;YouTube&lt;/strong&gt; ads) cannot be blocked by DNS alone.&lt;/li&gt;
&lt;li&gt;Some apps and devices (smart TVs, some phone apps) use &lt;strong&gt;hard-coded DNS&lt;/strong&gt; and ignore your settings.&lt;/li&gt;
&lt;li&gt;Browsers with &lt;strong&gt;secure DNS / DNS over HTTPS&lt;/strong&gt; can bypass Pi-hole unless disabled.&lt;/li&gt;
&lt;li&gt;Blocking is not perfect: some ads and trackers may still get through, and aggressive lists can break websites.&lt;/li&gt;
&lt;li&gt;If the Pi-hole computer is off, devices that rely on it have &lt;strong&gt;no DNS&lt;/strong&gt;. This is why a stable, always-on device is recommended.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the best result, combine Pi-hole with a browser extension such as &lt;strong&gt;uBlock Origin&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do I need to install anything on my phone?&lt;/strong&gt;&lt;br&gt;
No. Only change its DNS setting (or set DNS on the router).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Pi-hole slow down my internet?&lt;/strong&gt;&lt;br&gt;
No. Local DNS answers are fast, and cached answers return almost instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use it on Windows or macOS?&lt;/strong&gt;&lt;br&gt;
Yes, with Docker Desktop. For permanent use a Raspberry Pi or Linux server is better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do I still see ads?&lt;/strong&gt;&lt;br&gt;
Pi-hole blocks ad domains, not every ad. See Limitations and check that your browser's secure DNS is off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did my internet stop after I set the DNS?&lt;/strong&gt;&lt;br&gt;
The Pi-hole computer is off, asleep, has a different IP now, or cannot be reached. Set DNS back to automatic and check the Troubleshooting table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will it work if I change Wi-Fi networks?&lt;/strong&gt;&lt;br&gt;
Per-device DNS settings are saved per network. On other networks use a VPN (see Blocking ads outside your home).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is Pi-hole free?&lt;/strong&gt;&lt;br&gt;
Yes, it is free and open source.&lt;/p&gt;


&lt;h2&gt;
  
  
  Uninstall / undo everything
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Set DNS back to &lt;strong&gt;Automatic&lt;/strong&gt; on every device you changed (phone, PC, laptop, router).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Linux (NetworkManager):&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;nmcli connection modify &lt;span class="s2"&gt;"YOUR_WIFI_NAME"&lt;/span&gt; ipv4.ignore-auto-dns no ipv4.dns &lt;span class="s2"&gt;""&lt;/span&gt; ipv6.ignore-auto-dns no
   &lt;span class="nb"&gt;sudo &lt;/span&gt;nmcli connection up &lt;span class="s2"&gt;"YOUR_WIFI_NAME"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Stop and remove the container:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker stop pihole
   docker &lt;span class="nb"&gt;rm &lt;/span&gt;pihole
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Optionally delete its saved data:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker volume &lt;span class="nb"&gt;rm &lt;/span&gt;pihole
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(If you used Docker Compose with &lt;code&gt;./etc-pihole&lt;/code&gt;, delete that folder instead.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pi-hole website: &lt;a href="https://pi-hole.net/" rel="noopener noreferrer"&gt;https://pi-hole.net/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Pi-hole documentation: &lt;a href="https://docs.pi-hole.net/" rel="noopener noreferrer"&gt;https://docs.pi-hole.net/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Pi-hole Docker image: &lt;a href="https://hub.docker.com/r/pihole/pihole" rel="noopener noreferrer"&gt;https://hub.docker.com/r/pihole/pihole&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Pi-hole Docker documentation: &lt;a href="https://github.com/pi-hole/docker-pi-hole" rel="noopener noreferrer"&gt;https://github.com/pi-hole/docker-pi-hole&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docker installation: &lt;a href="https://docs.docker.com/get-started/get-docker/" rel="noopener noreferrer"&gt;https://docs.docker.com/get-started/get-docker/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Raspberry Pi Imager: &lt;a href="https://www.raspberrypi.com/software/" rel="noopener noreferrer"&gt;https://www.raspberrypi.com/software/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tailscale: &lt;a href="https://tailscale.com/" rel="noopener noreferrer"&gt;https://tailscale.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PiVPN: &lt;a href="https://pivpn.io/" rel="noopener noreferrer"&gt;https://pivpn.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Blocklist collection: &lt;a href="https://firebog.net/" rel="noopener noreferrer"&gt;https://firebog.net/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>ads</category>
      <category>containers</category>
      <category>network</category>
    </item>
    <item>
      <title>Flooky AI : Create tu propia IA</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Fri, 06 Jun 2025 08:54:57 +0000</pubDate>
      <link>https://dev.to/ciscoanass/flooky-ai-create-tu-propia-ia-285e</link>
      <guid>https://dev.to/ciscoanass/flooky-ai-create-tu-propia-ia-285e</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%2F1n6imcd3ab3qqson88mu.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%2F1n6imcd3ab3qqson88mu.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tutorial Práctico: Implementación de Flooky AI desde Cero
&lt;/h2&gt;

&lt;p&gt;Este tutorial documenta paso a paso cómo implementar Flooky AI, un chat de IA privado basado en la API de Claude, desde la creación de cuentas hasta el despliegue completo.&lt;/p&gt;




&lt;h2&gt;
  
  
  📋 Índice
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Creación de la cuenta Azure&lt;/li&gt;
&lt;li&gt;Configuración del proyecto en Azure DevOps&lt;/li&gt;
&lt;li&gt;Creación de los repositorios&lt;/li&gt;
&lt;li&gt;Instalación y configuración del agente de pipeline en WSL&lt;/li&gt;
&lt;li&gt;Despliegue de la infraestructura con Terraform&lt;/li&gt;
&lt;li&gt;Crear y configurar SonarQube localmente&lt;/li&gt;
&lt;li&gt;Despliegue de la aplicación Flooky AI&lt;/li&gt;
&lt;li&gt;Configuración del dominio y correo electrónico&lt;/li&gt;
&lt;li&gt;Configuración de Grafana y alertas en Slack&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Creación de la cuenta Azure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1. Registro en el portal de Azure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Abre &lt;strong&gt;portal.azure.com&lt;/strong&gt; y selecciona "Crear una cuenta gratuita"&lt;/li&gt;
&lt;li&gt;Regístrate con tu dirección de correo electrónico personal&lt;/li&gt;
&lt;li&gt;Introduce tus datos personales y de facturación&lt;/li&gt;
&lt;li&gt;Verifica tu identidad a través de SMS&lt;/li&gt;
&lt;li&gt;Proporciona tu tarjeta de crédito para verificación (no habrá cargos iniciales)&lt;/li&gt;
&lt;/ol&gt;

&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%2Fqzhyjj6op0lblyk60kba.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%2Fqzhyjj6op0lblyk60kba.png" alt=" " width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2. Creación del grupo de recursos
&lt;/h3&gt;

&lt;p&gt;Una vez dentro del portal:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;En el panel lateral izquierdo, haz clic en &lt;strong&gt;"Grupos de recursos"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"+ Crear"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Completa la información:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Suscripción&lt;/strong&gt;: Selecciona tu suscripción&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grupo de recursos&lt;/strong&gt;: &lt;code&gt;Anass-rg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Región&lt;/strong&gt;: &lt;code&gt;West Europe&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Revisar + crear"&lt;/strong&gt; y luego en &lt;strong&gt;"Crear"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;También puedes usar Azure CLI si prefieres la línea de comandos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az login
az group create &lt;span class="nt"&gt;--name&lt;/span&gt; flooky-ai-rg &lt;span class="nt"&gt;--location&lt;/span&gt; westeurope
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Configuración del proyecto en Azure DevOps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1. Creación de la organización y el proyecto
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Accede a &lt;strong&gt;dev.azure.com&lt;/strong&gt; e inicia sesión con la misma cuenta de Microsoft&lt;/li&gt;
&lt;li&gt;Crea una nueva organización:

&lt;ul&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"New organization"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Nombra la organización: &lt;strong&gt;"FlookyAI"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona la ubicación del host: &lt;strong&gt;"West Europe"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dentro de la organización, crea un nuevo proyecto:

&lt;ul&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"New project"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nombre&lt;/strong&gt;: &lt;code&gt;FlookyAI&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visibilidad&lt;/strong&gt;: &lt;code&gt;Private&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control de versiones&lt;/strong&gt;: &lt;code&gt;Git&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metodología de trabajo&lt;/strong&gt;: &lt;code&gt;Agile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Create project"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fjigb44d8th01wgj4l7in.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%2Fjigb44d8th01wgj4l7in.png" alt=" " width="432" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2. Generación del PAT (Personal Access Token)
&lt;/h3&gt;

&lt;p&gt;Para permitir la conexión del agente de pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Haz clic en tu avatar en la esquina superior derecha&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Personal Access Tokens"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"New Token"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configura el token con:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nombre&lt;/strong&gt;: &lt;code&gt;"FlookyAI-Pipeline-Agent"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organización&lt;/strong&gt;: &lt;code&gt;FlookyAI&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expiración&lt;/strong&gt;: &lt;code&gt;120 días&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope&lt;/strong&gt;: &lt;code&gt;Custom defined&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Pools&lt;/strong&gt;: &lt;code&gt;Read &amp;amp; manage&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build&lt;/strong&gt;: &lt;code&gt;Read &amp;amp; execute&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code&lt;/strong&gt;: &lt;code&gt;Read &amp;amp; write&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Connections&lt;/strong&gt;: &lt;code&gt;Read &amp;amp; query&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copia y guarda el token generado en un lugar seguro&lt;/strong&gt; (solo se muestra una vez)&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Nota&lt;/strong&gt;: Puedes generar más PAT para otras herramientas según sea necesario.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&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%2Fjmuh2rvvlrtroecjxrcs.png" alt=" " width="800" height="173"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  3. Creación de los repositorios
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1. Repositorio principal FlookyAI
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En Azure DevOps, ve a &lt;strong&gt;"Repos" &amp;gt; "Files"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Inicializa el repositorio con un README&lt;/li&gt;
&lt;li&gt;Crea la aplicación IA en este repositorio&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La aplicación está disponible en mi repositorio GitHub. Puedes clonar el repositorio con este comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/ciscoAnass/Flooky-AI.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Crea el archivo &lt;code&gt;azure-pipelines.yml&lt;/code&gt; para CI/CD:&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Configuración Inicial
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Default&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;webAppName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Flooky-WebApp'&lt;/span&gt;
  &lt;span class="na"&gt;azureSubscription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SC-SlothAI'&lt;/span&gt;
  &lt;span class="na"&gt;pythonVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.10'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El pipeline se activa automáticamente cuando hay cambios en la rama &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Se ejecuta en el grupo de agentes predeterminado&lt;/li&gt;
&lt;li&gt;Define tres variables importantes: nombre de la app web, la conexión de servicio de Azure, y la versión de Python a usar&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Etapa 1: Build
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;stage'&lt;/span&gt;
  &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BuildJob&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UsePythonVersion@0&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;versionSpec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(pythonVersion)'&lt;/span&gt;
        &lt;span class="na"&gt;addToPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Use&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$(pythonVersion)'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;python -m pip install --upgrade pip&lt;/span&gt;
        &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dependencies'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ArchiveFiles@2&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;rootFolderOrFile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(System.DefaultWorkingDirectory)'&lt;/span&gt;
        &lt;span class="na"&gt;includeRootFolder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="na"&gt;archiveType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;zip'&lt;/span&gt;
        &lt;span class="na"&gt;archiveFile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'&lt;/span&gt;
        &lt;span class="na"&gt;replaceExistingArchive&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Archive&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;files'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PublishBuildArtifacts@1&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;pathToPublish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(Build.ArtifactStagingDirectory)'&lt;/span&gt;
        &lt;span class="na"&gt;artifactName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;drop'&lt;/span&gt;
        &lt;span class="na"&gt;publishLocation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Container'&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Publish&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;artifacts'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Esta etapa prepara el código para el despliegue&lt;/li&gt;
&lt;li&gt;Configura el entorno con Python 3.10&lt;/li&gt;
&lt;li&gt;Actualiza pip e instala todas las dependencias del proyecto&lt;/li&gt;
&lt;li&gt;Crea un archivo ZIP con todos los archivos del proyecto&lt;/li&gt;
&lt;li&gt;Publica este ZIP como un "artefacto" llamado "drop" para usarlo en las siguientes etapas&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Etapa 2: Analysis
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Analysis&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SonarQube'&lt;/span&gt;
  &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
  &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;succeeded()&lt;/span&gt;
  &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SonarQube&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UsePythonVersion@0&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;versionSpec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.x'&lt;/span&gt;
        &lt;span class="na"&gt;addToPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;
        &lt;span class="s"&gt;pip install pytest pytest-cov&lt;/span&gt;
        &lt;span class="s"&gt;pytest --cov=. --cov-report=xml&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Setup&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Test'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SonarQubePrepare@7&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;SonarQube&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SonarQube-Local'&lt;/span&gt;
        &lt;span class="na"&gt;scannerMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CLI'&lt;/span&gt;
        &lt;span class="na"&gt;configMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;manual'&lt;/span&gt;
        &lt;span class="na"&gt;projectKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;FlookyAI_FlookyAI_acddf0f9-4761-4ebd-ba6b-e2bf470dfcaf'&lt;/span&gt;
        &lt;span class="na"&gt;projectName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;FlookyAI'&lt;/span&gt;
        &lt;span class="na"&gt;extraProperties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;sonar.sources=.&lt;/span&gt;
          &lt;span class="s"&gt;sonar.python.coverage.reportPaths=coverage.xml&lt;/span&gt;
          &lt;span class="s"&gt;sonar.exclusions=**/*.pyc,**/__pycache__/**,**/tests/**&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SonarQubeAnalyze@7&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SonarQubePublish@7&lt;/span&gt;
      &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;pollingTimeoutSec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;300'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Esta etapa analiza la calidad del código usando SonarQube&lt;/li&gt;
&lt;li&gt;Solo se ejecuta si la etapa de Build fue exitosa&lt;/li&gt;
&lt;li&gt;Configura Python y reinstala las dependencias&lt;/li&gt;
&lt;li&gt;Prepara SonarQube con la configuración necesaria para analizar el código Python&lt;/li&gt;
&lt;li&gt;Ejecuta las pruebas del proyecto y genera un informe de cobertura&lt;/li&gt;
&lt;li&gt;Realiza el análisis de código y publica los resultados en SonarQube&lt;/li&gt;
&lt;li&gt;Excluye archivos innecesarios como bytecode de Python y permite enfocarse en el código fuente real&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Etapa 3: Deploy
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Deploy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;stage'&lt;/span&gt;
  &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
  &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;succeeded()&lt;/span&gt;
  &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DeployJob&lt;/span&gt;
    &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Deploy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Azure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Web&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;App'&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;production'&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;runOnce&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# Deploy to Azure Web App&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AzureWebApp@1&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;azureSubscription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(azureSubscription)'&lt;/span&gt;
              &lt;span class="na"&gt;appType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;webAppLinux'&lt;/span&gt;
              &lt;span class="na"&gt;appName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(webAppName)'&lt;/span&gt;
              &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'&lt;/span&gt;
              &lt;span class="na"&gt;runtimeStack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PYTHON|3.10'&lt;/span&gt;
              &lt;span class="na"&gt;startupCommand&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-r&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;requirements.txt&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;gunicorn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;gunicorn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--bind=0.0.0.0:8000&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;app:app'&lt;/span&gt;
            &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Deploy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Azure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Web&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;App'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Esta etapa despliega la aplicación en Azure Web App&lt;/li&gt;
&lt;li&gt;Solo se ejecuta si la etapa de Build fue exitosa&lt;/li&gt;
&lt;li&gt;Define que se está desplegando en el entorno de "producción"&lt;/li&gt;
&lt;li&gt;Usa la tarea AzureWebApp para subir el archivo ZIP a la aplicación web de Azure&lt;/li&gt;
&lt;li&gt;Configura la aplicación para usar Python 3.10 en Linux&lt;/li&gt;
&lt;li&gt;Establece un comando de inicio que:

&lt;ul&gt;
&lt;li&gt;Instala las dependencias del proyecto&lt;/li&gt;
&lt;li&gt;Instala el servidor web Gunicorn&lt;/li&gt;
&lt;li&gt;Inicia la aplicación usando Gunicorn en el puerto 8000&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;La aplicación queda desplegada y funcionando en Azure&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.2. Repositorio de infraestructura
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;En Azure DevOps, crea un nuevo repositorio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Haz clic en el nombre del repositorio actual &amp;gt; &lt;strong&gt;"New repository"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nombre&lt;/strong&gt;: &lt;code&gt;FlookyAI-Infrastructure&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tipo&lt;/strong&gt;: &lt;code&gt;Git&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Añadir README&lt;/strong&gt;: Marcado&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Create"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Crea el archivo &lt;code&gt;main.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_resource_group"&lt;/span&gt; &lt;span class="s2"&gt;"rg"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Anass-RG"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_service_plan"&lt;/span&gt; &lt;span class="s2"&gt;"anass-webapp-plan"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Flooky-plan"&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;os_type&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Linux"&lt;/span&gt;
  &lt;span class="nx"&gt;sku_name&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"B2"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_linux_web_app"&lt;/span&gt; &lt;span class="s2"&gt;"FlookyAIWebApp"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Flooky-WebApp"&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;service_plan_id&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_service_plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;anass-webapp-plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;site_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;application_stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;python_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"3.9"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;always_on&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este archivo Terraform (&lt;code&gt;main.tf&lt;/code&gt;) configura recursos en Azure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utiliza un grupo de recursos existente llamado "Anass-RG"&lt;/li&gt;
&lt;li&gt;Crea un plan de servicio llamado "Flooky-plan" con tipo Linux y SKU B2&lt;/li&gt;
&lt;li&gt;Crea una aplicación web Linux llamada "Flooky-WebApp" que:

&lt;ul&gt;
&lt;li&gt;Usa el plan de servicio creado anteriormente&lt;/li&gt;
&lt;li&gt;Configura Python 3.9 como entorno de ejecución&lt;/li&gt;
&lt;li&gt;Mantiene la aplicación siempre activa (always on)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;En resumen&lt;/strong&gt;: es un script de infraestructura como código que despliega una aplicación web Python en Azure usando un grupo de recursos existente.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crea el archivo &lt;code&gt;provider.tf&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;azurerm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/azurerm"&lt;/span&gt;
        &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"4.8.0"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;features&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="nx"&gt;skip_provider_registration&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este fragmento de código Terraform configura:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El proveedor de Azure (azurerm) indicando que se usará la versión 4.8.0 del proveedor de HashiCorp&lt;/li&gt;
&lt;li&gt;Un backend de estado remoto en Azure (donde Terraform guardará el estado de la infraestructura), aunque los detalles específicos del backend no están definidos en este fragmento&lt;/li&gt;
&lt;li&gt;La configuración del proveedor Azure con opciones básicas:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;features {}&lt;/code&gt; activa características predeterminadas&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;skip_provider_registration = true&lt;/code&gt; evita que Terraform intente registrar los proveedores de recursos en Azure&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;En resumen&lt;/strong&gt;: este código establece la configuración necesaria para que Terraform pueda conectarse y gestionar recursos en Azure, usando un estado remoto almacenado también en Azure.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crea el archivo &lt;code&gt;azure-pipelines.yml&lt;/code&gt; para CI/CD:&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Configuración Inicial
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El pipeline se activa automáticamente cuando hay cambios en la rama &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Se ejecuta en el grupo de agentes predeterminado&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Paso 1: Instalación de Terraform
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformInstaller@1&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;terraformVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;latest'&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Instalar&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Terraform'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instala la última versión de Terraform en el agente&lt;/li&gt;
&lt;li&gt;Esta herramienta es necesaria para ejecutar los comandos de infraestructura como código&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Paso 2: Inicialización de Terraform
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformTaskV4@4&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azurerm'&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;init'&lt;/span&gt;
    &lt;span class="na"&gt;backendServiceArm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SC-SlothAI'&lt;/span&gt;
    &lt;span class="na"&gt;backendAzureRmResourceGroupName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Anass-RG'&lt;/span&gt;
    &lt;span class="na"&gt;backendAzureRmStorageAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;flookystorage'&lt;/span&gt;
    &lt;span class="na"&gt;backendAzureRmContainerName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;flookycontainer'&lt;/span&gt;
    &lt;span class="na"&gt;backendAzureRmKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;terraform.tfstate'&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Terraform&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Init'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inicializa Terraform (&lt;code&gt;terraform init&lt;/code&gt;) para preparar el entorno de trabajo&lt;/li&gt;
&lt;li&gt;Configura el backend remoto en Azure para guardar el estado de la infraestructura:

&lt;ul&gt;
&lt;li&gt;Usa la conexión de servicio 'SC-SlothAI' para autenticarse&lt;/li&gt;
&lt;li&gt;Almacena el estado en el grupo de recursos 'Anass-RG'&lt;/li&gt;
&lt;li&gt;Usa la cuenta de almacenamiento 'flookystorage'&lt;/li&gt;
&lt;li&gt;Guarda el archivo de estado en el contenedor 'flookycontainer'&lt;/li&gt;
&lt;li&gt;Nombra el archivo de estado como 'terraform.tfstate'&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Paso 3: Plan de Terraform
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformTaskV4@4&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azurerm'&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;plan'&lt;/span&gt;
    &lt;span class="na"&gt;environmentServiceNameAzureRM&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SC-SlothAI'&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Terraform&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Plan'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ejecuta &lt;code&gt;terraform plan&lt;/code&gt; para crear un plan de los cambios a realizar&lt;/li&gt;
&lt;li&gt;Este paso muestra qué recursos se crearán, modificarán o eliminarán&lt;/li&gt;
&lt;li&gt;Usa la conexión de servicio 'SC-SlothAI' para autenticarse con Azure&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Paso 4: Aplicación de Terraform
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TerraformTaskV4@4&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;azurerm'&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apply'&lt;/span&gt;
    &lt;span class="na"&gt;environmentServiceNameAzureRM&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SC-SlothAI'&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Terraform&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Apply'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ejecuta &lt;code&gt;terraform apply&lt;/code&gt; para implementar los cambios en la infraestructura&lt;/li&gt;
&lt;li&gt;Este paso crea o actualiza los recursos definidos en los archivos de Terraform&lt;/li&gt;
&lt;li&gt;Usa la conexión de servicio 'SC-SlothAI' para autenticarse con Azure&lt;/li&gt;
&lt;li&gt;Implementa automáticamente la infraestructura sin intervención manual&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Instalación y configuración del agente de pipeline en WSL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1. Instalación de WSL en Windows
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Abre PowerShell como administrador y ejecuta el comando para instalar WSL con Ubuntu:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Espera a que se complete la instalación&lt;/li&gt;
&lt;li&gt;Cuando se abra la terminal de Ubuntu, crea un usuario y contraseña&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4.2. Actualización de Ubuntu e instalación de dependencias
&lt;/h3&gt;

&lt;p&gt;Actualiza los paquetes del sistema:&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 update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instala las dependencias necesarias:&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; &lt;span class="nt"&gt;-y&lt;/span&gt; curl git libicu-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.3. Creación del usuario para el agente
&lt;/h3&gt;

&lt;p&gt;Crea un nuevo usuario para el agente:&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;adduser azagent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Añade el usuario al grupo sudo:&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;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;azagent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cambia al nuevo usuario:&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;su - azagent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.4. Descarga e instalación del agente
&lt;/h3&gt;

&lt;p&gt;Crea un directorio para el agente:&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;mkdir&lt;/span&gt; ~/agent &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Descarga el paquete del agente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://vstsagentpackage.azureedge.net/agent/3.227.2/vsts-agent-linux-x64-3.227.2.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extrae el paquete:&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;tar &lt;/span&gt;zxvf vsts-agent-linux-x64-3.227.2.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejecuta el script de configuración:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./config.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Durante la configuración, proporciona la siguiente información:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;URL del servidor&lt;/strong&gt;: &lt;code&gt;https://dev.azure.com/FlookyAI&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PAT&lt;/strong&gt;: Pega el token que generaste anteriormente&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nombre del pool de agentes&lt;/strong&gt;: &lt;code&gt;SelfHostedAgents&lt;/code&gt; (si no existe, se creará)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nombre del agente&lt;/strong&gt;: &lt;code&gt;WSL-Agent-01&lt;/code&gt; (o el nombre que prefieras)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instala el agente como servicio:&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; ./svc.sh &lt;span class="nb"&gt;install &lt;/span&gt;azagent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inicia el servicio:&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; ./svc.sh start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verifica que el servicio está en funcionamiento:&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; ./svc.sh status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.5. Verificación del agente en Azure DevOps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En Azure DevOps, ve a &lt;strong&gt;"Project settings"&lt;/strong&gt; (icono de engranaje en la parte inferior izquierda)&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Agent pools"&lt;/strong&gt; en el menú lateral&lt;/li&gt;
&lt;li&gt;Haz clic en el pool &lt;strong&gt;"SelfHostedAgents"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Verifica que tu agente aparece como &lt;strong&gt;"Online"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;El agente debe aparecer con status "Online" y estar listo para ejecutar jobs&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&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%2Fp8tbyko1cftsut72fq01.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%2Fp8tbyko1cftsut72fq01.png" alt=" " width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Despliegue de la infraestructura con Terraform
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1. Creación de recursos para el estado de Terraform
&lt;/h3&gt;

&lt;p&gt;Crea un grupo de recursos para el estado de Terraform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az group create &lt;span class="nt"&gt;--name&lt;/span&gt; tfstate &lt;span class="nt"&gt;--location&lt;/span&gt; westeurope
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crea una cuenta de almacenamiento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage account create &lt;span class="nt"&gt;--name&lt;/span&gt; anassstorage &lt;span class="nt"&gt;--resource-group&lt;/span&gt; tfstate &lt;span class="nt"&gt;--sku&lt;/span&gt; Standard_LRS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crea un contenedor de blobs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage container create &lt;span class="nt"&gt;--name&lt;/span&gt; tfstate &lt;span class="nt"&gt;--account-name&lt;/span&gt; anassstorage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.2. Creación de una conexión de servicio en Azure DevOps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En Azure DevOps, ve a &lt;strong&gt;"Project settings" &amp;gt; "Service connections"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"New service connection"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Azure Resource Manager"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Service principal (automatic)"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Completa la información:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scope level&lt;/strong&gt;: &lt;code&gt;Subscription&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription&lt;/strong&gt;: Selecciona tu suscripción&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource group&lt;/strong&gt;: &lt;code&gt;anass-rg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service connection name&lt;/strong&gt;: &lt;code&gt;SC-Flooky&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grant access to all pipelines&lt;/strong&gt;: Marcado&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Save"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  5.3. Creación y ejecución del pipeline de infraestructura
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En Azure DevOps, ve a &lt;strong&gt;"Pipelines" &amp;gt; "Pipelines"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"New pipeline"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Azure Repos Git"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona el repositorio &lt;strong&gt;"FlookyAI-Infrastructure"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Existing Azure Pipelines YAML file"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"/azure-pipelines.yml"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Revisa el pipeline y haz clic en &lt;strong&gt;"Run"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&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%2Ftkz4bwd7jh5l4u7kkts2.png" alt=" " width="800" height="370"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  6. Crear y configurar SonarQube localmente
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6.1. Instalar SonarQube Server en Ubuntu WSL
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Configuración de Requisitos Previos
&lt;/h4&gt;

&lt;p&gt;Primero, preparemos tu entorno Ubuntu WSL:&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="c"&gt;# Actualiza tu sistema&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Instala Java 17 (requerido por SonarQube)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-17-jdk &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Verifica la instalación de Java&lt;/span&gt;
java &lt;span class="nt"&gt;-version&lt;/span&gt;

&lt;span class="c"&gt;# Instala wget y unzip&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;wget unzip &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6.2. Instalar y Configurar SonarQube Community Edition
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Crear un usuario dedicado para SonarQube
&lt;/h4&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;adduser sonarqube
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;sonarqube
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Cambiar al usuario sonarqube
&lt;/h4&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;su - sonarqube
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Descargar SonarQube Community Edition (última versión LTS)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /opt
&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-10.3.0.82913.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Extraer SonarQube
&lt;/h4&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;unzip sonarqube-10.3.0.82913.zip
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;sonarqube-10.3.0.82913 sonarqube
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; sonarqube:sonarqube sonarqube
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configurar SonarQube
&lt;/h4&gt;

&lt;p&gt;Edita el archivo de configuración de SonarQube:&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 /opt/sonarqube/conf/sonar.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agrega estas líneas al archivo de configuración:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Configuración del servidor web
&lt;/span&gt;&lt;span class="py"&gt;sonar.web.host&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;
&lt;span class="py"&gt;sonar.web.port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;9000&lt;/span&gt;

&lt;span class="c"&gt;# Base de datos (usando H2 embebida para simplicidad)
&lt;/span&gt;&lt;span class="py"&gt;sonar.embeddedDatabase.port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;9092&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Iniciar SonarQube
&lt;/h4&gt;

&lt;p&gt;Navega al directorio bin de SonarQube:&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;cd&lt;/span&gt; /opt/sonarqube/bin/linux-x86-64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inicia SonarQube:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./sonar.sh start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verifica si está en ejecución:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./sonar.sh status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Espera unos minutos a que SonarQube se inicie por completo, luego accede desde tu navegador a: &lt;strong&gt;&lt;a href="http://localhost:9000" rel="noopener noreferrer"&gt;http://localhost:9000&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inicia sesión con &lt;code&gt;admin&lt;/code&gt;/&lt;code&gt;admin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Se te pedirá que cambies la contraseña: establece una nueva segura&lt;/li&gt;
&lt;li&gt;Completa el asistente de configuración inicial&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  6.3. Instalar y configurar SonarQube Scanner
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Descargar SonarQube Scanner
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /opt
&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Extraer el Scanner
&lt;/h4&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;unzip sonar-scanner-cli-5.0.1.3006-linux.zip
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;sonar-scanner-5.0.1.3006-linux sonar-scanner
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; sonarqube:sonarqube sonar-scanner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Añadir el scanner al PATH
&lt;/h4&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="s1"&gt;'export PATH="/opt/sonar-scanner/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6.4. Crear Tu Primer Proyecto
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En la interfaz web de SonarQube, haz clic en &lt;strong&gt;"Create Project"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Manually"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Introduce:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project key&lt;/strong&gt;: &lt;code&gt;Flooky-AI&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Display name&lt;/strong&gt;: &lt;code&gt;Flooky AI&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2F6i2niyj0v3nirmrhd7vo.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%2F6i2niyj0v3nirmrhd7vo.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fho4jldsdjjqana767ux3.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%2Fho4jldsdjjqana767ux3.png" alt=" " width="775" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Famkf4bc5h8u30powbavz.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%2Famkf4bc5h8u30powbavz.png" alt=" " width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Configurar el Proyecto para el Análisis
&lt;/h4&gt;

&lt;p&gt;Ve a la terminal y clona el repositorio de Flooky-AI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://fatimaassim20@dev.azure.com/fatimaassim20/FlookyAI/_git/FlookyAI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crea un archivo &lt;code&gt;sonar-project.properties&lt;/code&gt; en la raíz de tu proyecto:&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="c"&gt;# En el directorio de tu proyecto&lt;/span&gt;
nano sonar-project.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agrega este contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;sonar.projectKey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Flooky-AI&lt;/span&gt;
&lt;span class="py"&gt;sonar.projectName&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Flooky AI&lt;/span&gt;
&lt;span class="py"&gt;sonar.projectVersion&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1.0&lt;/span&gt;
&lt;span class="py"&gt;sonar.sources&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;
&lt;span class="py"&gt;sonar.host.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;http://localhost:9000&lt;/span&gt;
&lt;span class="py"&gt;sonar.token&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;TU_TOKEN_GENERADO_AQUÍ&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Ejecutar Tu Primer Análisis
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# En el directorio de tu proyecto&lt;/span&gt;
sonar-scanner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&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%2Fetv8y8qf5j3915f51gc9.png" alt=" " width="800" height="330"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  7. Despliegue de la aplicación Flooky AI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  7.1. Obtención de la API Key de Claude
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Regístrate en la plataforma de Anthropic para obtener acceso a la API de Claude: &lt;strong&gt;&lt;a href="https://www.anthropic.com/" rel="noopener noreferrer"&gt;https://www.anthropic.com/&lt;/a&gt;&lt;/strong&gt; y solicita acceso a la API&lt;/li&gt;
&lt;li&gt;Una vez aprobado, genera una clave API desde el dashboard:

&lt;ul&gt;
&lt;li&gt;Tu clave se verá similar a: &lt;code&gt;sk_ant_api_k3y123456789...&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fytb9hevl4v9ede6r1015.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%2Fytb9hevl4v9ede6r1015.png" alt=" " width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Guarda esta clave para utilizarla más adelante&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  7.2. Almacenamiento de la clave API en Azure Key Vault
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En el portal de Azure, busca y selecciona el Key Vault "flooky-ai-kv" creado por Terraform&lt;/li&gt;
&lt;li&gt;Ve a &lt;strong&gt;"Secrets" &amp;gt; "Generate/Import"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Completa la información:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Método de carga&lt;/strong&gt;: &lt;code&gt;Manual&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nombre&lt;/strong&gt;: &lt;code&gt;CLAUDE-API-KEY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Valor&lt;/strong&gt;: Pega tu clave API de Claude&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Create"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  7.3. Creación y ejecución del pipeline de la aplicación
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En Azure DevOps, ve a &lt;strong&gt;"Pipelines" &amp;gt; "Pipelines"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"New pipeline"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Azure Repos Git"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona el repositorio &lt;strong&gt;"FlookyAI"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Existing Azure Pipelines YAML file"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"/azure-pipelines.yml"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Revisa el pipeline y haz clic en &lt;strong&gt;"Run"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fgq1gtoaoe7v84nubv5g2.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%2Fgq1gtoaoe7v84nubv5g2.png" alt=" " width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7.4. Verificación del despliegue
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Una vez completado el pipeline, accede al portal de Azure&lt;/li&gt;
&lt;li&gt;Busca y selecciona el App Service "flooky-ai"&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Browse"&lt;/strong&gt; o en la URL para verificar que la aplicación está funcionando&lt;/li&gt;
&lt;/ol&gt;

&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%2Fetseqr4rr0dv6a100674.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%2Fetseqr4rr0dv6a100674.png" alt=" " width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Configuración del dominio y correo electrónico
&lt;/h2&gt;

&lt;h3&gt;
  
  
  8.1. Compra del dominio en Hostinger
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Accede a &lt;strong&gt;Hostinger&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Busca el dominio "flooky.space" y verifica su disponibilidad&lt;/li&gt;
&lt;li&gt;Añade el dominio al carrito y completa el proceso de compra&lt;/li&gt;
&lt;li&gt;Una vez adquirido, accede al panel de control de Hostinger&lt;/li&gt;
&lt;/ol&gt;

&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%2Fn9pnj214qc5wxsqaaiie.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%2Fn9pnj214qc5wxsqaaiie.png" alt=" " width="593" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  8.2. Configuración del dominio para Azure App Service
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En el portal de Azure, accede a tu App Service "flooky-ai"&lt;/li&gt;
&lt;li&gt;En el menú lateral, selecciona &lt;strong&gt;"Dominios personalizados"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Añadir dominio personalizado"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Sigue las instrucciones para obtener los registros DNS necesarios&lt;/li&gt;
&lt;li&gt;En el panel de control de Hostinger, ve a la sección &lt;strong&gt;"DNS / Nameservers"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Añade los registros DNS proporcionados por Azure:

&lt;ul&gt;
&lt;li&gt;Registro A para @&lt;/li&gt;
&lt;li&gt;Registro TXT para verificación&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Regresa a Azure y completa el proceso de validación y adición del dominio&lt;/li&gt;
&lt;/ol&gt;

&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%2Fc5x4hh01ldzkxv4po7cd.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%2Fc5x4hh01ldzkxv4po7cd.png" alt=" " width="588" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comprobamos que todo funciona y visitamos flooky.space&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  8.3. Configuración de SSL/TLS
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;En el App Service, ve a &lt;strong&gt;"TLS/SSL settings"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Para un certificado gratuito gestionado por Azure:

&lt;ul&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Private Key Certificates (.pfx)"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Create App Service Managed Certificate"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona tu dominio personalizado&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Create"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Una vez creado el certificado:

&lt;ul&gt;
&lt;li&gt;Ve a &lt;strong&gt;"SSL bindings"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Add SSL Binding"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecciona tu dominio y el certificado&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Add Binding"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Establece &lt;strong&gt;"HTTPS Only"&lt;/strong&gt; en &lt;strong&gt;"On"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  8.4. Configuración de Zoho Mail
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Accede a &lt;strong&gt;Zoho Mail&lt;/strong&gt; y regístrate&lt;/li&gt;
&lt;li&gt;Selecciona &lt;strong&gt;"Add an existing domain"&lt;/strong&gt; e introduce "flooky.space"&lt;/li&gt;
&lt;li&gt;Sigue las instrucciones para verificar la propiedad del dominio&lt;/li&gt;
&lt;li&gt;Configura los registros MX, SPF, DKIM y DMARC según las instrucciones de Zoho&lt;/li&gt;
&lt;li&gt;Crea las cuentas de correo necesarias: &lt;code&gt;hello@flooky.space&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Configura las firmas y ajustes adicionales según tus preferencias&lt;/li&gt;
&lt;/ol&gt;

&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%2Ffde92n6ior7irhvdtk30.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%2Ffde92n6ior7irhvdtk30.png" alt=" " width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fwezxyf9izm5pyvg4pcu4.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%2Fwezxyf9izm5pyvg4pcu4.png" alt=" " width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Configuración de Grafana y alertas en Slack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  9.1. Despliegue y Configuración de Grafana con Docker
&lt;/h3&gt;

&lt;p&gt;En el terminal de Ubuntu WSL ejecuta este comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;grafana &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; grafana-storage:/var/lib/grafana &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"GF_SECURITY_ADMIN_PASSWORD=Anass@1234"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;unless-stopped &lt;span class="se"&gt;\&lt;/span&gt;
  grafana/grafana:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Accede al navegador con este enlace: &lt;strong&gt;&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Ve a &lt;strong&gt;"Connection String"&lt;/strong&gt; y conecta tu cuenta Azure por ahí&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  9.2. Creación de dashboards
&lt;/h3&gt;

&lt;p&gt;Crea un nuevo dashboard:&lt;/p&gt;

&lt;p&gt;Configura paneles para monitorizar:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CPU y memoria del App Service:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memoria RAM&lt;/li&gt;
&lt;li&gt;Tiempo promedio de respuesta&lt;/li&gt;
&lt;li&gt;Requests&lt;/li&gt;
&lt;li&gt;Data Out&lt;/li&gt;
&lt;li&gt;Tráfico de Red&lt;/li&gt;
&lt;/ul&gt;

&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%2Fpwqvbhyw0hvao64nx8mj.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%2Fpwqvbhyw0hvao64nx8mj.png" alt=" " width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  9.3. Configuración de alertas en Slack
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Crea un canal en Slack para las alertas (ej. &lt;code&gt;#flooky-ai-alerts&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Instala la aplicación &lt;strong&gt;"Incoming WebHooks"&lt;/strong&gt; en tu workspace de Slack&lt;/li&gt;
&lt;/ol&gt;

&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%2Fo57lwj1t4mtpdxptmvuw.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%2Fo57lwj1t4mtpdxptmvuw.png" alt=" " width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Configurar grafana.ini
&lt;/h4&gt;

&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%2F38i7owtv958llglb9g6h.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%2F38i7owtv958llglb9g6h.png" alt=" " width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En Grafana:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ve a &lt;strong&gt;Alerting &amp;gt; Notification channels&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"New channel"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configura:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: &lt;code&gt;Slack Alerts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type&lt;/strong&gt;: &lt;code&gt;Slack&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL&lt;/strong&gt;: Pega la URL del webhook&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;"Test"&lt;/strong&gt; para verificar&lt;/li&gt;
&lt;li&gt;Guarda el canal de notificación&lt;/li&gt;
&lt;li&gt;Configura reglas de alerta para los paneles importantes&lt;/li&gt;
&lt;/ol&gt;

&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%2F5sbfvpl4yg3kb11o2euh.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%2F5sbfvpl4yg3kb11o2euh.png" alt=" " width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎉 ¡Felicidades!
&lt;/h2&gt;

&lt;p&gt;Has completado exitosamente la implementación de Flooky AI desde cero. Tu aplicación ahora debería estar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Desplegada en Azure Web App&lt;/li&gt;
&lt;li&gt;✅ Con un dominio personalizado (flooky.space) configurado&lt;/li&gt;
&lt;li&gt;✅ Con SSL/TLS habilitado&lt;/li&gt;
&lt;li&gt;✅ Integrada con pipelines de CI/CD en Azure DevOps&lt;/li&gt;
&lt;li&gt;✅ Con análisis de código en SonarQube&lt;/li&gt;
&lt;li&gt;✅ Monitoreada con Grafana&lt;/li&gt;
&lt;li&gt;✅ Con alertas configuradas en Slack&lt;/li&gt;
&lt;li&gt;✅ Con correo empresarial funcional&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📚 Recursos Adicionales
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/devops/" rel="noopener noreferrer"&gt;Documentación oficial de Azure DevOps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs" rel="noopener noreferrer"&gt;Documentación de Terraform para Azure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.sonarqube.org/latest/" rel="noopener noreferrer"&gt;Guía de SonarQube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grafana.com/docs/" rel="noopener noreferrer"&gt;Documentación de Grafana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.anthropic.com/" rel="noopener noreferrer"&gt;API de Claude - Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤝 Contribución
&lt;/h2&gt;

&lt;p&gt;Si encuentras algún error o tienes sugerencias de mejora, no dudes en:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crear un issue en el repositorio&lt;/li&gt;
&lt;li&gt;Enviar un pull request con tus mejoras&lt;/li&gt;
&lt;li&gt;Contactar al equipo de desarrollo&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  📝 Licencia
&lt;/h2&gt;

&lt;p&gt;Este proyecto está bajo la licencia MIT. Consulta el archivo &lt;code&gt;LICENSE&lt;/code&gt; para más detalles.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Desarrollado por&lt;/strong&gt;: Anass Assim&lt;br&gt;
&lt;strong&gt;Institución&lt;/strong&gt;: I.E.S Rodrigo Caro&lt;br&gt;
&lt;strong&gt;Curso&lt;/strong&gt;: Administración de Sistemas Informáticos en Red&lt;br&gt;
&lt;strong&gt;Fecha&lt;/strong&gt;: 2025&lt;/p&gt;

</description>
    </item>
    <item>
      <title>📝 Docker Images Cheat Sheet 🚀</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Sat, 08 Mar 2025 02:14:35 +0000</pubDate>
      <link>https://dev.to/ciscoanass/docker-images-cheat-sheet-2on3</link>
      <guid>https://dev.to/ciscoanass/docker-images-cheat-sheet-2on3</guid>
      <description>&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker pull nginx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pulls the latest Nginx image from Docker Hub.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker images&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists all Docker images on the local machine.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker ps&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists all running containers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker run -d nginx:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs an Nginx container in detached mode using the latest version.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker run -d -p 8080:80 nginx:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs Nginx in detached mode and maps port 8080 on the host to port 80 in the container.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker run -d -p 8080:80 -p 3000:80 nginx:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs Nginx in detached mode and maps multiple ports (8080 and 3000).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker ps -a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists all containers (including stopped ones).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker exec -it $ID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes a command inside a running container (replace &lt;code&gt;$ID&lt;/code&gt; with container ID).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker rm $(docker ps -aq)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Removes all stopped containers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker run --name "MyPage" -d -p 8080:80 nginx:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs a container named "MyPage" with port mapping.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cd /home/user/myhtml &amp;amp;&amp;amp; docker run --name "MyPage" -v $(pwd):/usr/share/nginx/html:ro -d -p 8080:80 nginx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs a container and mounts the local HTML folder to the container.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker exec -it $container_name bash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opens a bash shell in the running container (replace &lt;code&gt;$container_name&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docker run --name "copy-of-mypage" --volumes-from "mypage" -d -p 8081:80 nginx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs a new container using the same volumes as "mypage" and maps port 8081.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>docker</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>containers</category>
    </item>
    <item>
      <title>Tech and Tools I use</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Thu, 31 Oct 2024 22:24:57 +0000</pubDate>
      <link>https://dev.to/ciscoanass/tech-and-tools-i-use-193h</link>
      <guid>https://dev.to/ciscoanass/tech-and-tools-i-use-193h</guid>
      <description>&lt;h2&gt;
  
  
  A SysAdmin Essential Toolkit and Workstation Setup
&lt;/h2&gt;

&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%2F042hbsr7sjs32frlw3d1.jpg" 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%2F042hbsr7sjs32frlw3d1.jpg" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Here’s my toolkit and setup for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Personal development projects&lt;/li&gt;
&lt;li&gt;Work as a Systems Administrator&lt;/li&gt;
&lt;li&gt;Collaborative DevOps and security-focused projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code &amp;amp; Scripting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I primarily work with Visual Studio Code for coding and scripting. On Linux, I often turn to Sublime Text for a streamlined experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tech Stack :
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Primary Tools:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Automation &amp;amp; Infrastructure: Ansible, Docker, Terraform&lt;/li&gt;
&lt;li&gt;Scripting: Bash, Python, PowerShell&lt;/li&gt;
&lt;li&gt;Databases: MySQL&lt;/li&gt;
&lt;li&gt;Security &amp;amp; Monitoring: Wireshark, Zabbix, Nagios&lt;/li&gt;
&lt;li&gt;Testing Tools: pytest, Ansible Test&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Secondary Tools:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Web: Apache, NGINX&lt;/li&gt;
&lt;li&gt;Logging &amp;amp; Monitoring: Prometheus, Grafana&lt;/li&gt;
&lt;li&gt;Networking: Cisco Packet Tracer&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Some projects call for additional tools and APIs:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Providers: AWS, Google Cloud&lt;/li&gt;
&lt;li&gt;Payment APIs: PayPal, Bizum &lt;/li&gt;
&lt;li&gt;CI/CD: Jenkins, GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Providers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Website : &lt;a href="https://anass-assim.com/" rel="noopener noreferrer"&gt;www.anass-assim.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Domain Provider: Hostinger&lt;/li&gt;
&lt;li&gt;Hosting Provider : Github&lt;/li&gt;
&lt;li&gt;Mail Provider : &lt;a href="//hello@anass-assim.com"&gt;Zoho&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Growth &amp;amp; Networking
&lt;/h2&gt;

&lt;p&gt;For personal and professional growth, I focus on building and sharing secure, reliable tools. You can find my work on platforms like GitHub, Dev.to , Reddit .&lt;/p&gt;

&lt;h2&gt;
  
  
  Workstation &amp;amp; Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Laptop :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;CPU: Intel I7-1255U&lt;/li&gt;
&lt;li&gt;GPU: NVIDIA GeForce RTX 3060&lt;/li&gt;
&lt;li&gt;RAM: 32GB DDR4&lt;/li&gt;
&lt;li&gt;Storage: 1TB NVMe SSD + 2TB HDD &lt;/li&gt;
&lt;li&gt;Operating System: DUAL BOOT ( Ubuntu 24.04 and Windows 11 )&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Accessories
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keyboard: Logitech G213 Prodigy&lt;/li&gt;
&lt;li&gt;Mouse: Logitech G203 LIGHTSYNC&lt;/li&gt;
&lt;li&gt;Audio: Sony WH-CH720N&lt;/li&gt;
&lt;li&gt;Webcam: Logitech C270&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Home Server
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CPU : Intel Xeon E5-2670 &lt;/li&gt;
&lt;li&gt;GPU : Nvidia Geforce GTX 1660&lt;/li&gt;
&lt;li&gt;RAM : 8GB x 4 = 32GB DDR4&lt;/li&gt;
&lt;li&gt;STORAGE : 512GB SSD + 2TB HDD&lt;/li&gt;
&lt;li&gt;Case : Cougar Gemini M RGB&lt;/li&gt;
&lt;li&gt;Monitor : Lenovo D24-45 24'' + SAMSUNG LS24C310EAUXEN 24''&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Mobile
&lt;/h1&gt;

&lt;p&gt;Phone: Iphone 12&lt;br&gt;
Tablet: Samsung Galaxy Tab S7 &lt;/p&gt;

</description>
      <category>setup</category>
      <category>tools</category>
      <category>tech</category>
      <category>dev</category>
    </item>
    <item>
      <title>📝 Git Cheat Sheet 🚀</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Fri, 25 Oct 2024 22:34:51 +0000</pubDate>
      <link>https://dev.to/ciscoanass/git-cheat-sheet-2j1a</link>
      <guid>https://dev.to/ciscoanass/git-cheat-sheet-2j1a</guid>
      <description>&lt;h2&gt;
  
  
  📝 First Steps: Start and Configure A Git 🚀
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;git init&lt;/td&gt;
&lt;td&gt;Creates a new Git repository in the current folder.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git config --global -l&lt;/td&gt;
&lt;td&gt;Sets or views Git settings, like username and email ,...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git config $option "text"&lt;/td&gt;
&lt;td&gt;Sets a  Git configuration option to a specified value.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📅 Day-to-Day Work:
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;git status&lt;/td&gt;
&lt;td&gt;Displays the current status of the working directory and staging area.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git add $File_Name&lt;/td&gt;
&lt;td&gt;Stages a file for the next commit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git rm --cached $File_Name&lt;/td&gt;
&lt;td&gt;Untrack a file without deleting it locally.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git commit -m "Message"&lt;/td&gt;
&lt;td&gt;Records changes to the repository with a descriptive message.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git diff&lt;/td&gt;
&lt;td&gt;Displays differences between changes and the last commit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git log --oneline&lt;/td&gt;
&lt;td&gt;Displays a concise summary of commits in a single line.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git checkout $hash&lt;/td&gt;
&lt;td&gt;Switches to the specified commit by its hash.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git fetch&lt;/td&gt;
&lt;td&gt;Retrieves updates from the remote repository without merging.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git pull&lt;/td&gt;
&lt;td&gt;Fetches and merges updates from the remote repository.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git push&lt;/td&gt;
&lt;td&gt;Uploads local commits to the remote repository.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git restore $FileName&lt;/td&gt;
&lt;td&gt;Restores the specified file to the last committed state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git blame&lt;/td&gt;
&lt;td&gt;Shows line-by-line authorship for each line in a file.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git stash&lt;/td&gt;
&lt;td&gt;Temporarily saves changes that are not ready to be committed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;git tag&lt;/td&gt;
&lt;td&gt;Creates a marker for a specific commit, often used for releases.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📂 Files:
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;.gitconfig&lt;/td&gt;
&lt;td&gt;File Stores Git settings like username and preferences.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.gitignore&lt;/td&gt;
&lt;td&gt;file specifies files and directories for Git to ignore.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>gitlab</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>SysInfo Script</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Fri, 18 Oct 2024 23:25:15 +0000</pubDate>
      <link>https://dev.to/ciscoanass/sysinfo-script-23b3</link>
      <guid>https://dev.to/ciscoanass/sysinfo-script-23b3</guid>
      <description>&lt;h1&gt;
  
  
  SysInfo 🖥️: Track System Information 📊
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;This script gathers various system information such as disk usage, RAM usage, processes, IP addresses, last login details, SSH login information, and currently logged-in users.&lt;/li&gt;
&lt;/ul&gt;

&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%2Faw65sz85t5l2el7n5r8l.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%2Faw65sz85t5l2el7n5r8l.png" alt=" " width="800" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Description 📝
&lt;/h2&gt;

&lt;p&gt;The script utilizes several Linux commands to fetch and calculate system metrics, providing a snapshot of the system's current state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites ⚙️
&lt;/h2&gt;

&lt;p&gt;Before running the script, ensure you have &lt;code&gt;bc&lt;/code&gt; installed. If you're using Debian or a Debian-based distribution (like Ubuntu), you can install it with:&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-get update
 &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;bc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installation 📥
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Clone the repository:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git clone https://github.com/ciscoAnass/SysInfo.git
 &lt;span class="nb"&gt;cd &lt;/span&gt;SysInfo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Make the script executable:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x SysInfo.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the Script on Every Terminal Launch (Optional) 🚀
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If you want the script to run every time you open a terminal session, you can append the script path to ~/.bashrc using the following command:
&lt;/li&gt;
&lt;/ul&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;"~/SysInfo/SysInfo.sh"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This command appends the path to your script to the end of ~/.bashrc.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After appending, source ~/.bashrc to apply the changes:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now, the script will run automatically every time you open a new terminal session.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating a Command Alias 🔧
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If you want to create a command alias so you can execute the script by simply typing sysinfo, follow these steps:
&lt;/li&gt;
&lt;/ul&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;"alias sysinfo='~/SysInfo/SysInfo.sh'"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;-Source ~/.bashrc to apply the changes:&lt;/em&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;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can simply type sysinfo in your terminal to run the script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Output 🖨️
&lt;/h2&gt;

&lt;p&gt;After running the script, you will see output similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;System Information of &amp;lt;current_date&amp;gt;

Usage of / :             &amp;lt;DiskPer&amp;gt; of &amp;lt;DiskCapacity&amp;gt;
Memory Usage :           &amp;lt;RAM&amp;gt;%
Memory Swap :            &amp;lt;Swap&amp;gt;%
Total Processes :        &amp;lt;Processes&amp;gt;
Root Processes :         &amp;lt;RootProcesses&amp;gt;
IPv4 address  :         &amp;lt;ipv4&amp;gt;
IPv6 address :          &amp;lt;ipv6&amp;gt;
Last Login :            &amp;lt;lastlog&amp;gt;

&amp;lt;ssh_info&amp;gt;

Logged Users :           &amp;lt;LoggedUsers&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Contributing 🤝
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Contributions are welcome! Feel free to fork the repository and submit pull requests.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>basic</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Bulk Linux Users Creation</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Fri, 18 Oct 2024 23:23:20 +0000</pubDate>
      <link>https://dev.to/ciscoanass/bulk-linux-users-creation-10pk</link>
      <guid>https://dev.to/ciscoanass/bulk-linux-users-creation-10pk</guid>
      <description>&lt;h1&gt;
  
  
  Bulk User Creator (Linux)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Description
&lt;/h2&gt;

&lt;p&gt;This script automates the bulk creation of user accounts on a Linux system. It prompts for the username and the number of users to create. Usernames are generated based on the input and stored in a CSV file. Each user is created with a default password that matches their username.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Linux environment&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useradd&lt;/code&gt; command available&lt;/li&gt;
&lt;li&gt;To encrypt the password of the users using &lt;code&gt;mkpasswd&lt;/code&gt; , is it necesarry to install &lt;code&gt;whois&lt;/code&gt; Packet.
&lt;/li&gt;
&lt;/ul&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;whois
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repository:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/ciscoAnass/Bulk-Linux-User.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;Bulk-Linux-User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Make the script executable:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;chmod&lt;/span&gt; +x BulkUsers.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Command Alias (Optional but recommended)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add the following line to your shell configuration file (e.g., ~/.bashrc for bash):
&lt;/li&gt;
&lt;/ul&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;"alias bulkuser='sudo ~/Bulk-Linux-User/BulkUsers.sh'"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, apply the changes:&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;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Now you can use the bulkuser alias in your terminal to run the script with parameters. Here's how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To create 7 users with the username "poppy" (You can choose whatever Username you want to create , also numbers):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bulkuser poppy 7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This will generate output similar to:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;User &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy1 , Password&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy1&lt;/span&gt;
&lt;span class="na"&gt;User &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy2 , Password&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy2&lt;/span&gt;
&lt;span class="na"&gt;User &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy3 , Password&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy3&lt;/span&gt;
&lt;span class="na"&gt;User &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy4 , Password&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy4&lt;/span&gt;
&lt;span class="na"&gt;User &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy5 , Password&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy5&lt;/span&gt;
&lt;span class="na"&gt;User &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy6 , Password&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy6&lt;/span&gt;
&lt;span class="na"&gt;User &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy7 , Password&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poppy7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Additionally, it will create a UsrAccess-poppy.csv file containing the usernames and passwords.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Verification
&lt;/h2&gt;

&lt;p&gt;To verify that the users have been created correctly, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check User Accounts&lt;/strong&gt;:
List the last 7 users created on the system to ensure they have been created:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   getent passwd | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-7&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;: &lt;span class="nt"&gt;-f1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ensure you have the necessary permissions to execute user creation commands (useradd).&lt;/li&gt;
&lt;li&gt;Consider security implications when using default passwords.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>ubuntu</category>
      <category>debian</category>
    </item>
    <item>
      <title>DHCP Server</title>
      <dc:creator>Anass Assim</dc:creator>
      <pubDate>Fri, 18 Oct 2024 22:55:00 +0000</pubDate>
      <link>https://dev.to/ciscoanass/dhcp-server-46lj</link>
      <guid>https://dev.to/ciscoanass/dhcp-server-46lj</guid>
      <description>&lt;h2&gt;
  
  
  1- Network Setup :
&lt;/h2&gt;

&lt;p&gt;We assume the following network configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server (Debian 1) - Internal Network: 192.168.1.1/24&lt;/li&gt;
&lt;li&gt;Failover (Debian 2) - Internal Network: 192.168.1.2/24&lt;/li&gt;
&lt;li&gt;Relay (Debian 3) - 2 Interfaces (Internal Network):

&lt;ul&gt;
&lt;li&gt;IP in the Client Network: 192.168.1.3/24&lt;/li&gt;
&lt;li&gt;IP in the Server Network: 192.168.2.1/24&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Client (Debian 4) - Internal Network: 192.168.2.10/24&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;We will assign the IPs to the machines through the file &lt;strong&gt;/etc/network/interfaces&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server&lt;/strong&gt; : &lt;/li&gt;
&lt;/ul&gt;

&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%2Fp9qsh8adr50fekj2t667.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%2Fp9qsh8adr50fekj2t667.png" alt=" " width="573" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Failover&lt;/strong&gt; :&lt;/li&gt;
&lt;/ul&gt;

&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%2Fubivn7ilhm79r7mu3hof.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%2Fubivn7ilhm79r7mu3hof.png" alt=" " width="573" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relay&lt;/strong&gt; :&lt;/li&gt;
&lt;/ul&gt;

&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%2F96xplscljqwuf9vy7m7m.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%2F96xplscljqwuf9vy7m7m.png" alt=" " width="613" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;

&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%2Fccyykr2vt72675ig1g2y.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%2Fccyykr2vt72675ig1g2y.png" alt=" " width="614" height="366"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2- Installing Necessary Packages :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server&lt;/strong&gt; :
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt update
apt install isc-dhcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Failover&lt;/strong&gt; :
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt update
apt install isc-dhcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relay&lt;/strong&gt; :
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt update
apt install isc-dhcp-relay
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt; : &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No packages need to be installed on the client, but it is advisable to update the repository.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  3-Connectivity Check :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To check connectivity between the client and server, we usually ping from the client to the server or vice versa.&lt;/li&gt;
&lt;/ul&gt;

&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%2Fcgug948lg28pz4i2wjuw.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%2Fcgug948lg28pz4i2wjuw.png" alt=" " width="595" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, edit the network configuration file on the client, located at /etc/network/interfaces, and configure the enp0s3 interface in DHCP mode.&lt;/li&gt;
&lt;/ul&gt;

&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%2Fisfy34qyprhavrg3m9am.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%2Fisfy34qyprhavrg3m9am.png" alt=" " width="573" height="367"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3- Server Machine Configuration :
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;a- /etc/default/isc-dhcp-server :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edit the file /etc/default/isc-dhcp-server to configure the interface that will listen for client requests, which in this case will be enp0s3.&lt;/li&gt;
&lt;/ul&gt;

&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%2Fwm6tcbe7agemay72efzd.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%2Fwm6tcbe7agemay72efzd.png" alt=" " width="573" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b- /etc/dhcp/dhcpd.conf :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, configure the DHCP service on the server:&lt;/li&gt;
&lt;/ul&gt;

&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%2Fqsf56fok6ozy1ibb1t0n.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%2Fqsf56fok6ozy1ibb1t0n.png" alt=" " width="612" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we need to restart the DHCP service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl restart isc-dhcp-server
systemctl status isc-dhcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service should now be active.&lt;/p&gt;




&lt;h2&gt;
  
  
  4-Failover Machine Configuration :
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;a- /etc/default/isc-dhcp-server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just like on the server, we need to edit the file /etc/default/isc-dhcp-server to configure the interface that will listen for client requests, which in this case will be enp0s3.&lt;/li&gt;
&lt;/ul&gt;

&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%2Fre1gxkkx38i88nej0bog.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%2Fre1gxkkx38i88nej0bog.png" alt=" " width="785" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b- /etc/dhcp/dhcpd.conf&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, configure the DHCP service on the Failover:&lt;/li&gt;
&lt;/ul&gt;

&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%2F07vilfmf17jf0msc46rm.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%2F07vilfmf17jf0msc46rm.png" alt=" " width="612" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now we need to restart the DHCP service:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl restart isc-dhcp-server
systemctl status isc-dhcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service should now be active.&lt;/p&gt;




&lt;h2&gt;
  
  
  5-Relay Machine Configuration :
&lt;/h2&gt;

&lt;p&gt;*&lt;em&gt;a- Enable Forwarding: *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Edit the file /proc/sys/net/ipv4/ip_forward to allow packet forwarding between network interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo '1' &amp;gt; /proc/sys/net/ipv4/ip_forward
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;b- Client Network:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To make this change persistent after a reboot, edit the file /etc/sysctl.conf and add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "net.ipv4.ip_forward=1" &amp;gt; /etc/sysctl.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;c- /etc/default/isc-dhcp-relay&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this file, we need to add the IP of the server and the Failover, and set the two interfaces that connect to the client and the server. By default, these are usually “enp0s3” and “enp0s8” in VirtualBox.&lt;/p&gt;

&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%2Fw4xgfbt9ajyy82oryd39.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%2Fw4xgfbt9ajyy82oryd39.png" alt=" " width="613" height="522"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6- DHCP Verification:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Part 1: Server Check&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have finished configuring all machines (Server, RELAY, FAILOVER). Now it's time to check if the DHCP works correctly and if the client can obtain a dynamic IP from the server.&lt;/p&gt;

&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%2Faz8e6tgz4quh4qrdtjy5.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%2Faz8e6tgz4quh4qrdtjy5.png" alt=" " width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2: Failover Check&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After verifying that the client can obtain a dynamic IP from the server and everything works correctly, we can turn off the server or stop the isc-dhcp-server service to check if the client can obtain a dynamic IP from the Failover machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl stop isc-dhcp-server # On the Server Machine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&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%2F5440bebevck7wfe5gg2c.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%2F5440bebevck7wfe5gg2c.png" alt=" " width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dhcp</category>
      <category>network</category>
      <category>networking</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
