[{"content":"Host: Fedora Linux 44 KDE (x86_65) Target: Raspberry Pi 5 (ARM64) Tools: Podman, dd Container Image: quay.io/iamyaash/rpi5-bootc Firmware: github.com/worproject/rpi5-uefi 0. Build the container image and push it to quay.io Everything in this guide starts from a bootc container image, here quay.io/iamyaash/rpi5-bootc:latest.\nAlthough you need qemu-user-static to be installed on your host PC but I ran Podman to build the container image on a Raspberry Pi 5, so it won\u0026rsquo;t be needed.\nFROM --platform=linux/arm64 quay.io/fedora/fedora-bootc:42 # Install hardware utilities, firmware packages, and essentials RUN dnf -y install \\ NetworkManager \\ NetworkManager-wifi \\ wireless-regdb \\ linux-firmware \\ iproute \\ openssh-server \\ htop \u0026amp;\u0026amp; \\ dnf clean all # Ensure critical services start on boot RUN systemctl enable NetworkManager sshd Build the image: Run this in the project folder.\npodman build --platform linux/arm64 -f Containerfile.rpi -t quay.io/iamyaash/rpi5-bootc:latest . Push to quay.io:\npodman login quay.io podman push quay.io/iamyaash/rpi5-bootc:latest Pull it into root\u0026rsquo;s storage: bootc-image-builder runs under sudo and reads root\u0026rsquo;s container storage. Pull image there before the disk image.\nsudo podman pull quay.io/iamyaash/rpi5-bootc 1. Create the build configuration bootc-image-builder reads a config.toml that defines users. A bootc image has no default login, so this file is required if you want to login. Place this file into $HOME/bootc-config\n[[customizations.user]] name = \u0026#39;core\u0026#39; password = \u0026#39;core\u0026#39; key = \u0026#39;paste your ssh-rsa...public key\u0026#39; groups = [\u0026#39;wheel\u0026#39;] With a password set, you can easily login by connecting to a display and keyboard. It makes sense to use password because you can login even when the network is down. 2. Build disk.raw I would be running this command on Raspberry Pi 5, which would build the .raw file into ARM64 format.\nmkdir $HOME/bootc-build sudo podman run --rm --privileged --security-opt label=type:unconfined_t \\ -v ./bib-config.toml:/config.toml:ro \\ -v ./output:/output \\ -v /var/lib/containers/storage:/var/lib/containers/storage \\ quay.io/centos-bootc/bootc-image-builder:latest \\ --type raw \\ --target-arch arm64 \\ --rootfs ext4 quay.io/iamyaash/rpi5-bootc:latest Use this in case you want to run it in the background and log in later:\nnohup sudo podman run --rm --privileged --security-opt label=type:unconfined_t \\ -v ~/bootc-build/bib-config.toml:/config.toml:ro \\ -v ~/bootc-tmp:/output \\ -v /var/lib/containers/storage:/var/lib/containers/storage \\ quay.io/centos-bootc/bootc-image-builder:latest --type raw --rootfs ext4 quay.io/iamyaash/rpi5-bootc:latest \u0026gt; ~/bib.log 2\u0026gt;\u0026amp;1 \u0026amp; Copy the image to the Raspberry Pi 5 after finish building it.\n3. Setup the SD Card lsblk -d -o NAME,SIZE,MODEL,TRAN,RM sudo umount /dev/sda1/ /dev/sda2/ /dev/sda3 sudo wipefs -a /dev/sda sudo dd if=\u0026lt;image.raw\u0026gt; of=/dev/sda bs=4M conv=fsync status=progress sync sudo partprobe /dev/sda lsblk -f /dev/sda Expected Output: sda1 vfat(FAT16) EFI-SYSTEM 501 Mb sda2 ext4 boot 1 GB sda3 ext4 root (~10 GB)\n4. Merge the Pi 5 UEFI firmware Download this from github. https://github.com/worproject/rpi5-uefi\nmkdir -p ~/rpi5fw unzip -o \u0026lt;downloaded-filename\u0026gt;.zip -d ~/rpi5fw ls -R ~/rpi5fw sudo mkdir -p /mnt/efi sudo mount /dev/sda1 /mnt/efi findmnt /mnt/efi find /mnt/efi -maxdepth 3 | sort (The snippet below was generated by Claude. I forgot to copy this part from the earlier setup.)\nsudo rsync -rtv --no-perms --no-owner --no-group ~/rpi5fw/ /mnt/efi/ find /mnt/efi -maxdepth 3 | sort cat /mnt/efi/config.txt sync sudo umount /mnt/efi findmnt /mnt/efi || echo not-mounted Expected Output:\n/mnt/efi/RPI_EFI.fd /mnt/efi/bcm2712-rpi-5-b.dtb /mnt/efi/config.txt /mnt/efi/EFI/BOOT/BOOTAA64.EFI /mnt/efi/EFI/BOOT/fbaa64.efi /mnt/efi/EFI/fedora/ (shim, grub, grub.cfg and others) This is what makes the Pi 5 load the UEFI firmware.\nFirst Boot and Results I have just showed you how to build and flash into the SD Card. But the won\u0026rsquo;t be able to use Ethernet, Wifi and the Cooler Fan won\u0026rsquo;t work as well. But the USB works flawlessly.\nLog in by connecting a display and keyboard. Enter the password you set to log in. This is just an experimentation, and it only partially works. ","permalink":"https://docs.ayshell.dev/posts/bootc/rpi5-f42/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHost: Fedora Linux \u003cspan style=\"color:#ae81ff\"\u003e44\u003c/span\u003e KDE \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ex86_65\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTarget: Raspberry Pi \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eARM64\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTools: Podman, dd\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eContainer Image: quay.io/iamyaash/rpi5-bootc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFirmware: github.com/worproject/rpi5-uefi\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"0-build-the-container-image-and-push-it-to-quayio\"\u003e0. Build the container image and push it to quay.io\u003c/h1\u003e\n\u003cp\u003eEverything in this guide starts from a \u003ccode\u003ebootc\u003c/code\u003e container image, here \u003ccode\u003equay.io/iamyaash/rpi5-bootc:latest\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eAlthough you need \u003ccode\u003eqemu-user-static\u003c/code\u003e to be installed on your host PC but I ran Podman to build the container image on a Raspberry Pi 5, so it won\u0026rsquo;t be needed.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-Containerfile\" data-lang=\"Containerfile\"\u003eFROM --platform=linux/arm64 quay.io/fedora/fedora-bootc:42\n\n# Install hardware utilities, firmware packages, and essentials\nRUN dnf -y install \\\n    NetworkManager \\\n    NetworkManager-wifi \\\n    wireless-regdb \\\n    linux-firmware \\\n    iproute \\\n    openssh-server \\\n    htop \u0026amp;\u0026amp; \\\n    dnf clean all\n\n# Ensure critical services start on boot\nRUN systemctl enable NetworkManager sshd\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003cstrong\u003eBuild the image\u003c/strong\u003e:\nRun this in the project folder.\u003c/p\u003e","title":"Fedora bootc on a Raspberry Pi 5: Build, Flash, and Boot (Partial Support)"},{"content":"Checkout this documentation page which explains working with integration tests, in case you want to look at the official documentation.\nRunning Integration Tests Running integrations tests are simple in forgejo, as it uses make to run tests. Ensure you run this command before executing any tests:\nmake clean build Full-Suite Test As explained here, we can use make to run tests for each database:\nmake test-sqlite #runs tests using SQLite make test-pgsql #runs tests using PostgreSQL make test-mysql #runs tests using MySQL This runs the full-suite test using the respective database, in case you want to cover all tests.\nIndividual Test As explained here, we can run individual integration tests that cover specific parts of the test instead of running the full test suite.\nmake test-sqlite#GPG The part that starts with # is used to run isolated tests. We need to know the name of the function used in the test case.\nFor example, if you encounter an error in a specific part of the code, you should ensure that the error occurs within a defined test function:\nfunc doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) { ... } If the error originates within this function, you can use its name to run the individual test:\nmake test-sqlite#doAutoPRMerge OUTPUT: make test-sqlite#doAutoPRMerge | tail make test-sqlite#doAutoPRMerge | tail testing: warning: no tests to run ??? [TestLogger] 2025/09/24 17:34:15 modules/ssh/ssh.go:332:Listen() [I] Adding SSH host key: /home/iamyaash/Projects/codeberg/forgejo-official/tests/integration/gitea-integration-sqlite/data/ssh/gitea.rsa ??? [TestLogger] 2025/09/24 17:34:15 modules/ssh/init.go:28:Init() [I] SSH server started on localhost:2203. Cipher list ([chacha20-poly1305@openssh.com aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com]), key exchange algorithms ([mlkem768x25519-sha256 curve25519-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 diffie-hellman-group14-sha256 diffie-hellman-group14-sha1]), MACs ([hmac-sha2-256-etm@openssh.com hmac-sha2-256 hmac-sha1]) ??? [TestLogger] 2025/09/24 17:34:15 ...s/graceful/server.go:50:NewServer() [I] Starting new SSH server: tcp:localhost:2203 on PID: 1060294 ??? [TestLogger] 2025/09/24 17:34:15 ...er/issues/indexer.go:154:func2() [I] Issue Indexer Initialization took 10.028496ms ??? [TestLogger] 2025/09/24 17:34:15 ...exer/code/indexer.go:231:func4() [I] Repository Indexer Initialization took 9.958005ms ??? [TestLogger] 2025/09/24 17:34:15 ...exer/code/indexer.go:257:populateRepoIndexer() [I] Populating the repo indexer with existing repositories ??? [TestLogger] 2025/09/24 17:34:15 ...er/cleanup_sha256.go:27:CleanupSHA256() [I] Start to cleanup dangling images with a sha256:* version ??? [TestLogger] 2025/09/24 17:34:15 ...er/cleanup_sha256.go:106:cleanupSHA256() [I] Nothing to cleanup ??? [TestLogger] 2025/09/24 17:34:15 ...er/cleanup_sha256.go:29:CleanupSHA256() [I] Finished to cleanup dangling images with a sha256:* version PASS Note: Running a make commad to run test case will always initiate a debugserver in background and runs on tests on top of the running server.\nRunning Integration Test on Docker Container Pull this Docker Image: docker pull iamyaash8/playwright-forgejo:v1.54.2.1-noble Run the container while inside the Forgejo directory: docker run -it --rm -v .:/home/forgejo-tester/forgejo iamyaash8/playwright-forgejo:v1.54.2.1-noble Install Dependencies npx playwright install-deps \u0026amp;\u0026amp; npx playwright install By now, you should have all the required dependencies to run the integration test inside the container. Ensure you run this command before executing any tests:\nmake clean build Run individual test using this command:\nmake test-sqlite#GPG Or run full-suite test using these commands:\nmake test-sqlite #runs tests using SQLite make test-pgsql #runs tests using PostgreSQL make test-mysql #runs tests using MySQL Running E2E Tests Clean cached data \u0026amp; Build the binary: make clean #delete backend and integration files make clean all #delete backend, frontend and integration files make build #build everything make build frontend #build frontend files make build backend #build backend files Run these commands in case you run into any functional or visual error, while making changes or updating the code.\nRun Debug Server: make test-e2e-debugserver Debug server runs on port 3003 and it must run in the background to execute e2e tests.\nRunning Playwright E2E Tests: npx playwright test --ui It runs Playwright in UI mode which uses Chromium to simulate navigating and executing test on real time in browser and it shows the screen-shot as well.\nRunning Playwright Tests on Terminal npx playwright test tests/e2e/pr-review.test.e2e.ts npx playwright test tests/e2e/* # run e2e tests only # it\u0026#39;s flexible to use it the way you want Running Playwright Tests on UI npx playwright test --ui ","permalink":"https://docs.ayshell.dev/posts/forgejo/integration_tests/","summary":"A beginner-friendly guide to running integration tests in Forgejo. Learn how to execute individual tests, use tools like \u0026lsquo;make\u0026rsquo; and \u0026lsquo;go\u0026rsquo;, and explore the essential basics to help you get started with integration testing.","title":"Forgejo: Getting Started with Integration Tests \u0026 E2E Tests"},{"content":"Installing the Forgejo Runner Binary This guide walks you through downloading, verifying, and installing the Forgejo runner binary on Linux. By the end, you\u0026rsquo;ll have a runner registered with your Forgejo/Codeberg instance and running as a systemd service that starts automatically on boot.\nPrerequisites A Linux machine (x86_64 or ARM64) wget or curl, jq, gpg, and systemd Docker installed and running (required for running jobs) A Forgejo or Codeberg account with permission to create runners Step 1: Download and Verify the Binary First, determine your architecture and fetch the latest release:\n# Detect architecture (converts x86_64 → amd64, aarch64 → arm64) export ARCH=$(uname -m | sed \u0026#39;s/x86_64/amd64/;s/aarch64/arm64/\u0026#39;) # Get the latest version tag from Forgejo\u0026#39;s API export RUNNER_VERSION=$(curl -s https://data.forgejo.org/api/v1/repos/forgejo/runner/releases/latest | jq -r .name | cut -c 2-) # Construct the download URL export FORGEJO_URL=\u0026#34;https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-${ARCH}\u0026#34; # Download the binary and its signature wget -O forgejo-runner \u0026#34;${FORGEJO_URL}\u0026#34; || curl -o forgejo-runner \u0026#34;${FORGEJO_URL}\u0026#34; wget -O forgejo-runner.asc \u0026#34;${FORGEJO_URL}.asc\u0026#34; || curl -o forgejo-runner.asc \u0026#34;${FORGEJO_URL}.asc\u0026#34; Verify the GPG Signature Forgejo signs releases with their GPG key. Verify the binary before running it:\n# Import Forgejo\u0026#39;s public key gpg --keyserver hkps://keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710 # Verify the signature gpg --verify forgejo-runner.asc forgejo-runner \u0026amp;\u0026amp; echo \u0026#34;✓ Verified\u0026#34; || echo \u0026#34;✗ Verification failed\u0026#34; If verification fails, do not run the binary—re-download and try again.\nStep 2: Install the Binary Make the binary executable and move it to a directory in your PATH:\nchmod +x forgejo-runner sudo cp forgejo-runner /usr/local/bin/forgejo-runner Test the installation:\nforgejo-runner -v # Should output something like: forgejo-runner version 8.0.0 ... Step 3: Create a Dedicated Runner User Run the runner as a dedicated non-root user for security:\n# Create user with a home directory sudo useradd --create-home --shell /bin/bash forgejo-runner-user # Add to docker group so the runner can spawn job containers sudo usermod -aG docker forgejo-runner-user Note: Log out and back in (or reboot) for the docker group change to take effect.\nStep 4: Generate the Initial Configuration Switch to the runner user and generate a default config file:\nsudo su - forgejo-runner-user forgejo-runner generate-config \u0026gt; ~/runner-config.yml This creates ~/runner-config.yml with sensible defaults. We\u0026rsquo;ll customize it next.\nStep 5: Configure the Runner Edit ~/runner-config.yml (or use sed/cat as shown below) to make three changes:\n1. Set Labels Labels determine which jobs this runner can execute. Replace the empty labels: [] with your desired labels:\nlabels: - ubuntu-latest:host - ubuntu-22.04:host - docker:host Tip: Use label:host format for runners that execute jobs directly on the host. See Forgejo docs for more label formats.\n2. Add Your Forgejo/Codeberg Connection Log into your Forgejo or Codeberg instance:\nGo to Settings → Actions → Runners Click Create new runner Copy the generated configuration (it contains url, uuid, and token) Paste it under connections: in your config:\nconnections: forgejo: url: https://codeberg.org/ # or your Forgejo instance URL uuid: your-runner-uuid-here token: your-runner-token-here 3. Save the file Your runner-config.yml should now have both labels and connections populated.\nStep 6: Test the Runner Manually Before setting up systemd, verify everything works:\n# Still as forgejo-runner-user forgejo-runner daemon -c ~/runner-config.yml You should see output indicating the runner connected and is waiting for jobs. Check your Forgejo/Codeberg runner list—it should show as Online. Press Ctrl+C to stop.\nStep 7: Create a Systemd Service Run the runner automatically on boot and restart on failure.\nCreate the service file # Exit back to your sudo user (Ctrl+D or \u0026#39;exit\u0026#39;) sudo nvim /etc/systemd/system/forgejo-runner.service Paste the following configuration:\n[Unit] Description=Forgejo Runner Documentation=https://forgejo.org/docs/latest/admin/actions/ After=docker.service Requires=docker.service [Service] Type=simple User=forgejo-runner-user WorkingDirectory=/home/forgejo-runner-user ExecStart=/usr/local/bin/forgejo-runner daemon -c /home/forgejo-runner-user/runner-config.yml ExecReload=/bin/kill -s HUP $MAINPID Restart=on-failure RestartSec=10 TimeoutStopSec=infinity # Security hardening NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=read-only ReadWritePaths=/home/forgejo-runner-user [Install] WantedBy=multi-user.target Security notes: The hardening options above restrict the service\u0026rsquo;s filesystem access. Adjust ReadWritePaths if your runner needs access to other directories.\nStep 8: Enable and Start the Service sudo systemctl daemon-reload sudo systemctl enable --now forgejo-runner.service sudo systemctl status forgejo-runner.service The runner should now be active (running). Verify in your Forgejo/Codeberg UI that the runner appears Online.\nTroubleshooting Issue Solution Runner shows Offline Check journalctl -u forgejo-runner -f for errors; verify url, uuid, token in config docker: permission denied Ensure forgejo-runner-user is in the docker group and you\u0026rsquo;ve rebooted/logged out Jobs stuck in Pending Check labels match job requirements; verify Docker is running Binary won\u0026rsquo;t run Re-verify GPG signature; ensure architecture matches (uname -m) Updating the Runner When a new version is released:\n# Stop the service sudo systemctl stop forgejo-runner # Re-run Step 1 (download \u0026amp; verify new binary) # ... download commands from Step 1 ... # Replace binary sudo cp forgejo-runner /usr/local/bin/forgejo-runner # Restart sudo systemctl start forgejo-runner References:\nInstallation from binary, Forgejo Docs Latest v16 Author\u0026rsquo;s note: The technical content and steps in this post are my own. AI was used only for grammar correction and formatting improvements.\n","permalink":"https://docs.ayshell.dev/posts/forgejo/runner-install-binary/","summary":"A step-by-step guide to installing the Forgejo runner as a standalone binary, configuring it as a systemd service, and connecting it to your Forgejo or Codeberg instance.","title":"Forgejo: Installing and Configuring the Forgejo Runner Binary"},{"content":"Overview The kubectl describe command is used to inspect K8s resources in detail, describe command provides detailed information while get commands provides a summarized output. It aggregates information from multiple source to give a comprehensive snapshot of a resource\u0026rsquo;s lifecycle including resource configuration, status, events, dependencies and more. This command is particularly useful for debugging and troubleshooting as it highlights why a resource may not be functioning as expected.\nMain Sources for Aggregating Information When you kubectl describe, Kubernetes API server dynamically queries 3 distinct data sources to build your output:\nSources:\netcd database via API server. kubelet process running on the active worker node. The Kubernetesd Event resource database. The Desired State (etcd) Pulls the information about the container images, environment variables, storage volume, definitions, resource requests/limits, and node selectors. The Current Live Status Pulls the information about real-time diagnostics straight from the container runtime engine such as containerd. Outputs Current status such running, waiting, terminated, pending\u0026hellip; IP address allocated to the pod Last State \u0026amp; Exit Code Total Restart Counts The Cluster Event Log Pulls information on a completely separate stream of time-stamped cluster actions related to that specific pod. The Events section at the very bottom, it tells chronological story of the resource. Example: Successfully Pulling Image -\u0026gt; Created Container -\u0026gt; Started Container -\u0026gt; Unhealthy -\u0026gt; Killing Container Output Details The output of kubectl describe typically includes:\nMetadata: name, namespace, labels, annotations Spec: resource config, container images, ports, and environment variables Status and Conditions: readiness, phase, and QoS class Volumes: mounted storage and persistent volume claims Events: lifecycle events such scheduling, image pulling, and error like ImagePullBackOff or ErrImagePull How to Use Print a detailed description of the resource, you may select a singly object by\nname, type, name prefix, label selector, and more. kubectl describe TYPE NAME_PREFIX Common Usage\n# describe a pod kubectl describe pod uptime-kuma-deployment-7c78854f7d-vbfm5 # describe a node kubectl describe node k3s-agent # describe all nodes kubectl describe nodes # descibe all pods kubectl describe pods # describe pods by label kubectl describe pods -l name=LABEL_NAME Best Practices Use kubectl describe as first step in troubleshooting before diving into logs. Combine with label selectors to filter efficiently. For large clusters, consider chunked output to avoid overwhelming the terminal. --chunk-size int (default: 500) Remember that namespace context is ignored if listing across all namespaces with -A or --all-namespaces. Example kubectl get pods -o wide Sample Pods List:\nNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES bazarr-deployment-76b9585465-29jp2 1/1 Running 0 15h 10.42.3.20 k3s-agent-debian-laptop \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; filebrowser-deployment-6cb698b868-vrphs 1/1 Running 0 15h 10.42.3.16 k3s-agent-debian-laptop \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; forgejo-deployment-5f585676d-h5snf 1/1 Running 2 (155m ago) 4d20h 10.42.2.18 k3s-server \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; grafana-deployment-699fdbc48d-2kcv6 1/1 Running 2 (155m ago) 7d18h 10.42.2.7 k3s-server \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; jellyfin-deployment-64f97df8cb-b68k4 1/1 Running 1 (155m ago) 3d22h 10.42.2.19 k3s-server \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; prowlarr-deployment-7c5f76dd7f-2kqhp 1/1 Running 0 15h 10.42.3.19 k3s-agent-debian-laptop \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; radarr-deployment-8566c6c7b6-m5w97 1/1 Running 0 15h 10.42.3.21 k3s-agent-debian-laptop \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; semaphore-deployment-97cc8965f-c7pn8 1/1 Running 2 (155m ago) 7d19h 10.42.2.3 k3s-server \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; sonarr-deployment-769bb45458-8bvwz 1/1 Running 0 15h 10.42.3.18 k3s-agent-debian-laptop \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; transmission-deployment-554fdbcf5d-hr222 1/1 Running 0 15h 10.42.3.17 k3s-agent-debian-laptop \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; trilium-deployment-75c7ff4655-dhd42 1/1 Running 2 (155m ago) 7d19h 10.42.2.9 k3s-server \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; uptime-kuma-deployment-7c78854f7d-vbfm5 1/1 Running 2 (155m ago) 7d19h 10.42.2.4 k3s-server \u0026lt;none\u0026gt; \u0026lt;none\u0026gt; Looking closely at pods list, there is a very obvious clue here:\nForgejo, Grafana, Trilinium, Uptime Kuma, all restarted exactly 153 minutes ago. Because they all restarted at the exact same time while your other pods stayed online. This is the absolute perfect scenario to use kubectl describe.\nTo inspect the pods that recently restarted, you provide the resource type pod followed by the exact name:\n# Investigate the Grafana restart kubectl describe pod grafana-deployment-699fdbc48d-2kcv6 Output:\nkubectl describe pod grafana-deployment-699fdbc48d-2kcv6 Name: grafana-deployment-699fdbc48d-2kcv6 Namespace: default Priority: 0 Service Account: default Node: k3s-server/192.168.31.11 Start Time: Wed, 01 Jul 2026 18:57:19 +0530 Labels: app=grafana pod-template-hash=699fdbc48d Annotations: kubectl.kubernetes.io/restartedAt: 2026-07-01T18:47:44+05:30 Status: Running IP: 10.42.2.7 IPs: IP: 10.42.2.7 Controlled By: ReplicaSet/grafana-deployment-699fdbc48d Containers: grafana: Container ID: containerd://27bb751597488860d091f054053059351f53d29e0442006ee421d2d9cdfe3bfa Image: grafana/grafana-enterprise:latest Image ID: docker.io/grafana/grafana-enterprise@sha256:68a7ee3dc2c726e54b2be3533a9e1ac6baaed0893334947a6378520de28a6a76 Port: 3000/TCP (grafana-port) Host Port: 0/TCP (grafana-port) State: Running Started: Thu, 09 Jul 2026 11:09:26 +0530 Last State: Terminated Reason: Unknown Exit Code: 255 Started: Sun, 05 Jul 2026 14:55:37 +0530 Finished: Thu, 09 Jul 2026 11:08:48 +0530 Ready: True Restart Count: 2 Environment: \u0026lt;none\u0026gt; Mounts: /var/lib/grafana from grafana-storage (rw) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bb9w6 (ro) Conditions: Type Status PodReadyToStartContainers True Initialized True Ready True ContainersReady True PodScheduled True Volumes: grafana-storage: Type: HostPath (bare host directory volume) Path: /grafana/data HostPathType: Directory kube-api-access-bb9w6: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt Optional: false DownwardAPI: true QoS Class: BestEffort Node-Selectors: hardware-type=heavy-compute Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: \u0026lt;none\u0026gt; Exit Code 255: Look closely at the Containers: block under Last State:: Last State: Terminated Reason: Unknown Exit Code: 255 Started: Sun, 05 Jul 2026 14:55:37 +0530 Finished: Thu, 09 Jul 2026 11:08:48 +0530 The Timeline: The container ran smoothly for 4 days straight (from July 5th to July 9th) until it abruptly died at exactly 11:08:48 AM today. It was successfully brought back up by K3s less than a minute later at 11:09:26 AM. What this means: Exit Code 255 is a catch-all meaning the main process inside the container abruptly stopped with an exit status out of range or the underlying service runtime cut it off without a specific signal. The Empty Event Log Why is it empty? Kubernetes event logs only live in memory for 1 hour by default before they are wiped. Because the crash happened roughly 2.5 hours ago, the cluster-level event history for that exact crash window has already aged out.\nEvents have a limited retention time and triggers and messages may evolve with time. Event consumers should not rely on the timing of an event with a given Reason reflecting a consistent underlying trigger, or the continued existence of events with that Reason. Events should be treated as informative, best-effort, supplemental data.\nWhat\u0026rsquo;s the Problem?: Well, in my case there has been power outage and it came back within a minute. I guess it explain why it stopped abruptly. When a container is gracefully stopped by Kubernetes, its receives a signal to shutdown cleanly and leaves an exit code like 0. Why my control plane lost power it didn\u0026rsquo;t have the time to clean up. That\u0026rsquo;s why the container lost its connection to the processes mid-execution. When the node booted back up, containerd looked at what happened right before the blackout, couldn\u0026rsquo;t find a clean exit signature, and flagged it as Exit Code: 255 with Reason: Unknown.\n","permalink":"https://docs.ayshell.dev/posts/kubectl/describe/","summary":"This post explains how to get detailed description of the specific or group resources using describe command. This provides a human-readable overview of k8s resources on status, events, configs and relationships with other components.","title":"Kubectl: Show Details of Specific/Group Resources"},{"content":"Introduction Swap Space plays a vital role in managing memory on Linux for maintaining performance. When your system runs out of RAM, it can use the swap space to keep runningg applications, but it\u0026rsquo;s slower a than RAM and depends on the storage device you use on your system.\nHow It Works? When a system starts running low on RAM, the Linux operating system uses a swap space to prevent applications from crashing. Instead of immediately terminating processes, the kernel identifies memory pages that are inactive or least recently used and moves them from RAM to a reserved area on disk known as Swap.\nThis process is called paging. By freeing up RAM in this way, the system can continue running active processes smoothly. If a process later needs data access that was moved from RAM to Swap, it can swap out other inactive pages to make space.\nSwap Space can be,\nDedicated Partition Swap File Combination of Swap Partitions \u0026amp; Swap Files btrfs doesn\u0026rsquo;t support swap space.\nHowever, swap space must not be considered a full replacement for RAM, since swap space are located in storage devices(HDD, SSD) which have slower memory R/W speed. A heavy reliance on swap can lead to noticeable performance degradation, often referring to as thrashing. (where system spends more time swapping than executing tasks.)\nModern Linux systems also uses additional optimizations such as :\nSwappiness: A kernel parameter that controls how aggressively the system swap space. ZRAM/ZSwap: Compressed in-memory swap techniqures that reduce disk I/O and improve performance. Page Cache Management: The kernel may drop cached data before swapping, depending on memory pressure. Recommended Swap Space? In years past, the recommended amount of swap space increased linearly with the amount of RAM in the system. However, modern systems often include hundreds of gigabytes of RAM. As a consequence, recommended swap space is considered a function of system memory workload, not system memory. Checkout this Recommended System Swap Space.\nRAM in System Recommended Swap Space Recommended Swap Space (allowing hibernation) \u0026lt;= 2GB 2x the amount of RAM 3 times the amount of RAM \u0026gt; 2GB - 8GB Equal to the amount of RAM 2 times the amount of RAM \u0026gt; 64GB At least 4GB Hibernation not recommended \u0026gt; 8GB - 64GB At least 4GB 1.5 times the amount of RAM Increase Swap Memory (Swap File) Note: This method is only suitable for non-btrfs type filesystems.\nCheck the available swap memory: # Lists active swap devices/files swapon --show NAME TYPE SIZE USED PRIO /dev/zram0 partition 8G 0B 100 Note: Many modern Fedora systems use zram (compressed RAM swap) by default instead of disk-based swap.\n# Shows overall memory and swap usage free -h total used free shared buff/cache available Mem: 15Gi 6.9Gi 1.9Gi 148Mi 6.8Gi 8.2Gi Swap: 8.0Gi 0B 8.0Gi Creating a swap file: sudo fallocate -l 1G /swapfile fallocate is fast because it allocates space without writing zeros.\n# use dd if fallocate is not supported sudo dd if=/dev/zero of=/swapfile bs=1024 count=65536 Set the right permission for the created swap file: sudo chmod 600 /swapfile This restricts access so only root can read/write the swap (required for security + recommended)\nMaking swap file: sudo mkswap /swapfile # prepares the swapfile to be used as swap space Make Swap Persistent: Without this, the swap will disappear after reboot. echo \u0026#39;/swapfile swap swap defaults 0 0\u0026#39; | sudo tee -a /etc/fstab sudo systemctl daemon-reload # ensures the swap file automatically enabled at boot. Activating swap file: sudo swapon /swapfile # activates the swapfile immediately (non-persistent) Verify the change: swapon --show free -h You should now see /swapfile listed alongside any existing swap.\nCheckout this post to know how to create swap partition which is recommended on btrfs file type filesystems.\n","permalink":"https://docs.ayshell.dev/posts/linux/swap-space/swap-file/","summary":"Linux swap memory is a portion of disk storage used as virtual memory to supplement RAM, allowing the system to continue running when physical memory is full.","title":"Linux: Fundamentals of Swap Space"},{"content":"What is drain? kubectl drain is a command used in Kubernetes to safely evict all pods from a node in preparation for maintenance or updates, ensuring minimal disruption to services.\nIt marks a node as unschedulable (cordon) and then it gracefully evicts all running pods, allowing them to be reschedulable on other nodes. This command ensures preventing service interruptions, and handles everything smoothly during maintenance.\nkubectl drain NODE_NAME Detailed Explanation The drain command marks the node unschedulable to prevent new pods from arriving. It evicts the pods if the API server supports eviction, else it will delete the pods.\nThe Daemon set-managed pods cannot be drain\u0026rsquo;ed without using --ignore-daemonsets, because those pods would immediately be replaced by the daemon set controller, which ignores unschedulable markings.\nkubectl drain NODE_NAME --ignore-daemonsets If there are any pods that are neither mirror pods nor managed by a:\nReplication Controller Replica Set Daemon Set Stateful Set Job then, the drain will not delete any pods unless you use --force, which will allow deletion to proceed if the managing resource of one or more pods is missing.\n# drain even if they are not managed by (above mentioned) kubectl drain NODE_NAME --force # abort drain if they are not managed by (above mentioned) kubectl drain NODE_NAME --grace-period=900 Essential Commands Local data used by pods are deleted when the node is drained. kubectl drain NODE_NAME --delete-emptydir-data DELETE pods even if eviction is supported. (Bypasses checking PodDisruptionBudgets) kubectl drain NODE_NAME --disable-eviction Terminating pods gracefully within the given seconds/time kubectl drain NODE_NAME --grade-period=8 #-1 uses the default value specified in pod Duration before giving up, (0 = infinite) kubectl drain NODE_NAME --timeout-duration The above mentioned commands are the one you\u0026rsquo;ll most probably use everyday, but checkout the official documentation to learn more about other available options.\nExample Using drain command to rename the nodes, Checkout this post to learn more.\nIn order to rename the node:\nDrain the node (On Control Plane) kubectl drain NODE_NAME --ignore-daemonsets --delete-emptydir-data Stop the systemd service and rename the hostname (On Worker Node) sudo systemctl stop k3s-agent.service sudo hostnamectl set-hostname NEW_HOSTNAME Update the records in /etc/host(On Worker Node) # i.e: rename `OLD_HOSTNAME` to `NEW_HOSTNAME` sudoedit /etc/hosts Delete the node (On Control Plane) kubectl delete node NODE_NAME Reinstall k3s-agent (On Worker Node) Copy node-token sudo cat /var/lib/rancher/k3s/server/node-token Execute the installation script curl -sfL https://get.k3s.io | K3S_URL=https://192.168.31.11:6443 K3S_TOKEN=\u0026lt;token\u0026gt; K3S_NODE_NAME=\u0026lt;NEW_HOSTNAME\u0026gt; sh - This is one of the way I use drain often times to re-register k3s-agents. But there are other ways to use it as well, this is just an example to give you an overall idea of how drain command plays a vital role in evicting pods without breaking stuff.\n","permalink":"https://docs.ayshell.dev/posts/kubectl/drain/","summary":"This post explains how to safely evict pods using the drain command. It covers how the drain command works behind the scenes, includes the essential commands you need, and ends with a practical example to demonstrate its usage.","title":"Kubectl: Safely Drain A Node"},{"content":"TLDR Changing /etc/hosts or even the system hostname does not always rename an already-joined k3s node in place; Kubernetes node objects are tied to the name used at registration time. SO if the agent was installed when the hostname was debian, the cluster will keep showing debian until that node rejoins as k3s-agent.\nStandard Procedure To Change Node Name On the machine you want to change the name, stop the agent and reinstall or restart it with the new node name explicity set as k3s-agent.\nOn the worker node: (We\u0026rsquo;re changing name of your agent only)\nStop the k3s service: sudo systemctl stop k3s-agent Use drain command to evict the pods and other services: sudo kubectl drain debian --ignore-daemonsets --delete-emptydir-data Change the \u0026lt;OLD_HOSTNAME\u0026gt; using hostnamectl: sudo hostnamectl set-hostname k3s-agent Update the \u0026lt;OLD_HOSTNAME\u0026gt; from /etc/hosts to k3s-agent: sudoedit /etc/hosts Delete the debian node (on Control Plane): kubectl delete node debian Reinstall k3s-agent On the workder node, reinstall or re-run the agent:\n# copythe node-token sudo cat /var/lib/rancher/k3s/server/node-token curl -sfL https://get.k3s.io | K3S_URL=https://192.168.31.11:6443 K3S_TOKEN=\u0026lt;token\u0026gt; K3S_NODE_NAME=\u0026lt;NEW_HOSTNAME\u0026gt; sh - Enter the updated hostname in `\u0026lt;NEW_HOSTNAME\u0026gt;\nOn the control place, check the list of node:\nkubectl get nodes What to do: If you want the old worker back in service, simply uncordon it:\nkubectl uncordon debian That removes the unschedulable state and lets pods land there again.\nIn my case, all the existing pods are pointing to hardware-type=media-server, so I just have to update the new worker label:\nkubectl label node k3s-agent hardware-type=media-server kubectl get pods -w Kubernetes uses labels and selectors exactly for this kind of placement control, and a pod with a nodeSelector will only schedule onto nodes that match it.\nWhat to Expect: Once the node label matches, the Pending pods should begin scheduling if there are no other blockers like PVCs, taints, or resource limits.\nCaution Do not remove labels from other nodes unless you mean to shift workloads away from them. Adding the label to the new node is usually safer than changing every manifest.\n","permalink":"https://docs.ayshell.dev/posts/kubectl/rename-node/","summary":"This post shows how to rename a k3s node using the standard drain, rejoin, and relabel procedure. It walks through changing the hostname, replacing the old node entry, and restoring workload scheduling on the new node.","title":"Kubectl: Renaming the Nodes"},{"content":"What is keyd? A key remapping daemon for linux.\nKeyd is a lightweight key remapping tool for Linux that gives you precise control over your keyboard. It can remap keys, create custom shortcuts, and simulate keystrokes to help you streamline repetitive actions. With keyd, you can tailor your keyboard behavior to match your workflow and improve productivity. It can even\nGetting Started Install Install from source:\ngit clone https://github.com/rvaiya/keyd cd keyd make \u0026amp;\u0026amp; sudo make install sudo systemctl enable --now keyd Configuration I have an extra keyboard, so I use keyd to simulate keystrokes only from the other keyboard.\nFind the exact device ID: sudo keyd monitor After running this command, press keys on the keyboard you want to use for macros. It will display the keyboard name, ID, and other information.:\ndevice added: 3151:4011:a2a3d108 ROYUAN 2.4G Wireless Keyboard Mouse (/dev/input/event8) device added: 3151:4011:59783b6a ROYUAN 2.4G Wireless Keyboard (/dev/input/event7) device added: 3151:4011:e9545600 ROYUAN 2.4G Wireless Keyboard System Control (/dev/input/event6) device added: 3151:4011:acb87de2 ROYUAN 2.4G Wireless Keyboard Consumer Control (/dev/input/event5) device added: 3151:4011:5b3db59a ROYUAN 2.4G Wireless Keyboard (/dev/input/event4) device added: 320f:5055:9a3865d9 Evision RGB Keyboard Mouse (/dev/input/event29) device added: 320f:5055:4714f8e7 Evision RGB Keyboard (/dev/input/event27) device added: 320f:5055:10914b4b Evision RGB Keyboard (/dev/input/event26) Copy the ID that starts after \u0026lsquo;device added: \u0026rsquo;. In this, we\u0026rsquo;ll be using 320f:5055:10914b4b (from Evision RGB Keyboard) Create configuration file: sudo mkdir -p /etc/keyd/ sudo touch /etc/keyd/default.conf Add the ID in default.conf: sudo $EDITOR /etc/keyd/default.conf [ids] 320f:5055:10914b4b Add Macros The shortcuts and keys will change depends on desktop environment. In my case, I\u0026rsquo;m using Fedora 44 KDE Plasma.\nI use KDE\u0026rsquo;s native shortcut configuration tool to assign custom shortcuts, and then I use keyd to trigger those shortcuts when I press specific keys on a specific keyboard. This was my early configuration, but keep in mind these shortcuts won\u0026rsquo;t work on your PC unless you assign the custom shortcuts in KDE Shortcuts Configuration tool and use keyd simulate them.\n│ File: default.conf 1 │ [ids] 2 │ 320f:5055:10914b4b 3 │ 4 │ [main] 5 │ #screen-shot 6 │ f5 = macro(print) 7 │ #screen-record 8 │ f6 = macro(M-S-r) 9 │ 10 │ [control] # control + \u0026lt;key\u0026gt; 11 │ #essentials 12 │ e = macro(M-e) #dolphin-filemanager 13 │ . = macro(M-.) #emoji-picker 14 │ #entertainment 15 │ d = macro(C-S-A-d) #discord 16 │ s = macro(C-S-A-s) #steam 17 │ #browser 18 │ f = macro(C-S-A-f) #firefox 19 │ z = macro(C-S-A-z) #zen 20 │ c = macro(C-S-A-c) #chromium 21 │ m = macro(C-S-A-m) #edge 22 │ w = macro(C-S-A-w) #waterfox ","permalink":"https://docs.ayshell.dev/posts/macros/keyd-essentials/","summary":"Use keyd to create macros with more control, so they run only when keys are pressed on a specific keyboard. I will also show the installation, setup, and configuration steps.","title":"Managing Keyboard Control and Macros with keyd"},{"content":"Overview K3s locks the cluster configuration file (/etc/rancher/k3s/k3s.yaml) to the root user by default. By default, you are forced to prefix every command with sudo just to authenticate with the API server. If you ever get tired of typing sudo before every single command, you can give your regular $USER user permission to read the cluster config.\nMethod 1 mkdir -p ~/.kube sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config sudo chown $USER:$USER ~/.kube/config Once you do that, you can drop the sudo entirely and just run:\nkubectl get pods If you still get this warning try the \u0026ldquo;METHOD 2\u0026rdquo;:\nWARN open /etc/rancher/k3s/config.yaml: permission denied Method 2 You can completely silence these permissions warnings by telling kubectl to only look at your local user config file. Run this command on your Raspberry Pi 5:\necho \u0026#34;export KUBECONFIG=\\$HOME/.kube/config\u0026#34; \u0026gt;\u0026gt; ~/.bashrc source ~/.bashrc Method 3 If the KUBECONFIG trick didn\u0026rsquo;t silence it on K3s, your kubectl command is actually a symlink running k3s kubectl under the hood. Before it even looks at your pod configuration, the core k3s wrapper binary always checks /etc/rancher/k3s/config.yaml to see if there are global cluster configuration options.\nBecause your standard user account lacks read permissions for that system configuration directory, the K3s CLI wrapper throws those annoying warning lines. We can fix this permanently by updating the file permissions::\nsudo chmod 644 /etc/rancher/k3s/config.yaml This basically allows the standard user $USER to safely read (644) the basic configuration parameters without giving away any administrative root or write access:\nNow try kubectl without sudo:\nkubectl get pods ","permalink":"https://docs.ayshell.dev/posts/kubectl/no-sudo-access-kubectl/","summary":"This guide outlines three proven methods to configure passwordless non-root kubectl access in a K3s cluster. It covers setting up your local user context, adjusting system file permissions, and permanently silencing annoying configuration permission warnings.","title":"Kubectl: Running kubectl Without sudo (and Fixing Permission Warnings)"},{"content":"Overview On many laptop\u0026rsquo;s KDE\u0026rsquo;s charge-limit slider is only a frontend, and the settings are reset after reboot. Because, the firmware/kernel does not persist it reliably. The usual fix is to apply the limit at boot with a persistent rule or service, instead of relying on KDE Plasma alone.\nGood Approach Writing a systemd service is a standard and reasonable workaround when the KDE setting does not survice the reboot on your hardware. It\u0026rsquo;s not the most elegant solution, but it gets the job done and it\u0026rsquo;s a common Linux way to reapply a battery threshold at boot.\nSolution Create a system service file named battery-charge-limit.service in /etc/systemd/system. That is the normal location for custom systemd unit files, while the vendor provided units usually live under /usr/lib/systemd/system or something similar.\nVerify Battery Location and Threshold Check your actual battery path first, because some laptops use a different battery name or different thresholds.\nfind /sys/class/power_supply/BAT1 -type f | grep -E \u0026#34;charge_control_(start|end)_threshold\u0026#34; Note: BAT1 maybe be different in your machine\nHead inside /etc/systemd/system cd /etc/systemd/system Create a file named battery-charge-limit.service sudo touch battery-charge-limit.service Open the .service with choice of your editor: $EDITOR battery-charge-limit.service Add these lines [Unit] Description=Set battery charge limit to 80% ConditionPathExists=/sys/class/power_supply/BAT1/charge_control_end_threshold [Service] Type=oneshot ExecStart=/bin/bash -c \u0026#39;echo 80 \u0026gt; /sys/class/power_supply/BAT1/charge_control_end_threshold\u0026#39; [Install] WantedBy=multi-user.target This example assumes your battery is BAT1 and the threshold file is charge_control_end_threshold, which is common but not universal.\nApply the Changes After saving the file, reload systemd so it notices the new unit, then enable it so it runs automatically at boot:\n#reloads the units to detect new file sudo systemctl daemon-reload #always starts at boot sudo systemctl enable --now battery-charge-limit.service ","permalink":"https://docs.ayshell.dev/posts/kde/battery-charge-limit/","summary":"Quick guide on how to limit battery charge level in KDE using systemd service.","title":"KDE: Limiting Battery Charging Level"},{"content":"What are Docker Volumes? Docker volumes are a mechanism for persisting data independently of the container lifecycle. Since, the data in a container will be deleted once the container is stopped, using Docker volumes ensures the data is stored permenently.\nVolumes are managed by Docker and stored on the host (mostly under /var/lib/docker/volumes). Most importantly, it allows the data to be stored, retained and shared between container, suriving container restarts and removals. It preferrable to use for stateful applications like databases or file servers where data persistence matters. Creating and Using Volumes Volumes can be created implicitly by Docker when referenced or explicitly using: docker volume create \u0026lt;volume_name\u0026gt; Start a container and mount a volume: docker run -it -v \u0026lt;volume_name\u0026gt;:/path/in/container \u0026lt;image:tag\u0026gt; Volume Content Persistence and Sharing Files written/modified inside the container at the mount point path persist on the volume. When a new container mounts the same volume, it can process the previously stored data. Volumes can be mounted read-write (default) or read-only with :ro option: docker run -it -v \u0026lt;volume_name\u0026gt;:/container/path/:ro \u0026lt;image:tag\u0026gt; Inspecting and Managing Volumes List volumes: docker volume ls Inspect a volume for details like mount point: docker volume inspect \u0026lt;volume_name\u0026gt; Remove a Volume(only when inactive/not being by any containers) docker volume rm \u0026lt;volume_name\u0026gt; Thoughts If you read this posts about Bind Mounts, using Volumes over Bind Mount is a benefit because:\nVolumes provide better data management via Docker CLI (create, inspect remove) They are portable and flexible, supporting various storage backend beyond local host paths. More suitable for production and complex setups than bind mounts. Most importantly, it provides data storage isolation as modifying the data inside volume won\u0026rsquo;t damage the internal system storage. ","permalink":"https://docs.ayshell.dev/posts/docker/volumes/","summary":"\u003ch1 id=\"what-are-docker-volumes\"\u003eWhat are Docker Volumes?\u003c/h1\u003e\n\u003cp\u003eDocker volumes are a mechanism for persisting data independently of the container lifecycle. Since, the data in a container will be deleted once the container is stopped, using Docker volumes ensures the data is stored permenently.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eVolumes are managed by Docker and stored on the host (mostly under \u003ccode\u003e/var/lib/docker/volumes\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eMost importantly, it allows the data to be stored, retained and shared between container, suriving container restarts and removals.\u003c/li\u003e\n\u003cli\u003eIt preferrable to use for stateful applications like databases or file servers where data persistence matters.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"creating-and-using-volumes\"\u003eCreating and Using Volumes\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVolumes can be created implicitly by Docker when referenced or explicitly using:\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker volume create \u0026lt;volume_name\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003eStart a container and mount a volume:\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker run -it -v \u0026lt;volume_name\u0026gt;:/path/in/container \u0026lt;image:tag\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"volume-content-persistence-and-sharing\"\u003eVolume Content Persistence and Sharing\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFiles written/modified inside the container at the mount point path persist on the volume.\u003c/li\u003e\n\u003cli\u003eWhen a new container mounts the same volume, it can process the previously stored data.\u003c/li\u003e\n\u003cli\u003eVolumes can be mounted \u003ccode\u003eread-write\u003c/code\u003e (\u003cem\u003edefault\u003c/em\u003e) or \u003ccode\u003eread-only\u003c/code\u003e with \u003ccode\u003e:ro\u003c/code\u003e option:\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker run -it -v \u0026lt;volume_name\u0026gt;:/container/path/:ro \u0026lt;image:tag\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"inspecting-and-managing-volumes\"\u003eInspecting and Managing Volumes\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eList volumes:\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker volume ls\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003eInspect a volume for details like mount point:\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker volume inspect \u0026lt;volume_name\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003eRemove a Volume(\u003cem\u003eonly when inactive/not being by any containers\u003c/em\u003e)\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker volume rm \u0026lt;volume_name\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"thoughts\"\u003eThoughts\u003c/h1\u003e\n\u003cp\u003eIf you read this posts about \u003ca href=\"https://iamyaash.github.io/spells/posts/docker/mount-volume/\"\u003e\u003cstrong\u003eBind Mounts\u003c/strong\u003e\u003c/a\u003e, using Volumes over Bind Mount is a benefit because:\u003c/p\u003e","title":"Docker: Persistent Storage Using Volumes"},{"content":"Overview I keep seeing this error on Fedora KDE Plasma. I doubt that it\u0026rsquo;s actually an error from KDE Plasma itself, and I don\u0026rsquo;t think Fedora is responsible either.\nWhenever I try to use external headphones or any audio device, the GUI menu does not list them separately as distinct audio devices. Instead, I have to make it work by routing the audio through the internal speaker’s virtual device name, rather than showing the device separately. Weirdly, some applications send audio to the internal speakers while other audio plays through the headphones simultaneously, which is inconsistent and difficult to troubleshoot.\nNo matter what I try, it always results in errors. I believe the best way to fix this issue is to reset the audio configuration entirely instead of troubleshooting individual settings manually.\nReinstall Tools I installed the pipewire tools instead of pipewire-pulseaudio, which changed some configurations and caused audio device errors.\nInstall the pipewire-pulseaudio package first: sudo dnf install pipewire-pulseaudio --allowerasing This will remove the conflicting package package and install thee pipewire-pulseaudio instead.\nAdd the user to the group for appropriate permissions: sudo usermod -aG audio $USER Try reinstalling or updating pipewire and related packages again to check if we have the same error:\\ sudo dnf reinstall pipewire pipewire-alsa wireplumber Verify that pipewire, pipewire-pulseaudio, pulseaudio-alsa and wireplumber are installed correctly: sudo dnf list installed pipewire\\* Restart the pipewire and related services for the current user and reboot system as well: systemctl --user restart pipewire pipewire-pulse wireplumber sudo reboot ","permalink":"https://docs.ayshell.dev/posts/kde/audio-reset/","summary":"Quick guide on how to reset audio configurations in KDE.","title":"KDE: Reset Audio Configurations"},{"content":" Mounting At Runtime Into A Container docker run --name \u0026lt;container_name\u0026gt; -v \u0026lt;absolute_local_path\u0026gt;:\u0026lt;absolute_container_path\u0026gt; run --name \u0026lt;container_name\u0026gt;: Name of the running container -v \u0026lt;local-path\u0026gt;:\u0026lt;container-path\u0026gt;: Local directory path (left-side) \u0026amp; Container directory path (right-side) Mounting At Startup Time Into A Container docker run -it --rm -v local/path:container/path image:tag -i(interactive): Keeps STDIN open so you can interact with the container even if not attached. It allows you to send input to the container. -t(tty): Allocates a pseudo-TTY terminal inside the container. This makes the container\u0026rsquo;s console more readable and interactive, like a normal terminal sessions. --rm: Automatically removes the container when it exits. Prevents stopped containers from running in the background, and cleans up after the container stop running. -v local/path:/container/path: Bind mounts a directory or file form the host machine to the container\u0026rsquo;s file system at runtime. Changes made locally will be reflected immediately in the container, since it\u0026rsquo;s was mounted not copied. image:tag: Name of the Docker image and it\u0026rsquo;s respective tag. ","permalink":"https://docs.ayshell.dev/posts/docker/mount-volume/","summary":"A short guide on mounting a local directory inside a container.","title":"Docker: Using Bind Mounts (Volume Mount)"},{"content":"What is SSH Agent? SSH agent is a daemon for SSH that keeps track of identity keys and their passphrases in memory (not on disk). Which improves security and convenience. When an SSH key with a passphrase is used, the agent prompts for the passphrase only once per login session, and then handles authentication for future connections automatically. The agent only allows the stored keys to sign authentication messages, never allowing the private key material to be extracted. Main Uses Single Sign-On (SSO): Enter the password once per login session, then use SSH seamlessly across multiple terminals and program without needing to authenticate. Agent Forwarding: Allows remote SSH sessions to use your local agent, making it possible to authenticate to further hosts without needing to copying the private keys around. Key Management: Easily add, remove, and list keys managed by the agent, improving operational security and ease of use. Example: ssh-add Usage (Manual) To use ssh-agent in Linux, start the agent, add your private key, and optionally configure it for automatic use and forwarding.\nStart ssh-agent: eval \u0026#34;$(ssh-agent -s)\u0026#34; Add SSH key to agent: ssh-add ~/.ssh/id_rsa #example output from my device Enter passphrase for \u0026lt;sensitive-info\u0026gt;.ssh/id_rsa: Identity added: \u0026lt;sensitive-info\u0026gt;.ssh/id_rsa (email@email.com) Verify added keys: ssh-add -l #example output from my device 4096 SHA256:\u0026lt;asdasdasdasdasdasdasdasdasdasdasdasdasdasdas\u0026gt; email@email.com (RSA) Automatic Start Using Systemd Units Create ssh-agent.service: Location: .config/systemd/user/ssh-agent.service\nOwnership: sudo chmod $USER:$USER .config/systemd/user/ssh-agent.service\nPermission: sudo chmod 644 .config/systemd/user/ssh-agent.service\n[Unit] Description=SSH Key Agent For All Users After=network.target [Service] Type=simple Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK ExecStop=/usr/bin/pkill -u $USER ssh-agent [Install] WantedBy=default.target Add Environment Variable $SSH_AUTH_SOCK in .bashrc: #ssh-agent environment variable for user systemd export SSH_AUTH_SOCK=\u0026#34;$XDG_RUNTIME_DIR/ssh-agent.socket\u0026#34; Start the service: sudo systemctl daemon-reload sudo systemctl --user enable --now ssh-agent sudo systemctl --user start ssh-agent sudo systemctl --user status ssh-agent ","permalink":"https://docs.ayshell.dev/posts/ssh/ssh-agent/","summary":"SSH agent is a background program that manages and storess SSH private keys for secure authentication, letting users connect to remote servers via SSH without repeatedly entering passphrase or password.","title":"SSH: Agent"},{"content":"What is GPG / PGP? GnuPG (aka GPG) is an implementation of standard known as PGP (Pretty Good Privacy). It uses a system of \u0026ldquo;Public\u0026rdquo; and \u0026ldquo;Private\u0026rdquo; keys for the encryption and signing of message or data.\nPrivate Key Private keys are the first half of a GPG key which is used to decrypt messages that are encrypted using public keys. Also used for signing messages - a way to prove that you own the key. Obviously, you must not share the private keys anywhere. Public Key Public keys are the second half of a GPG key which is used to encrypt messages for the owner of private key. It is safe to share it anywhere publicly, as it can only be used to encrypt messages for the owner of the private key. In simple terms, owning just the public key is useless unless you own the private key. Why Use GPG? GPG (GNU Privacy Guard) provides encryption and digital signing to:\nProtect the confidentiality and integrity of your communications. Authenticate the sender of messages or files. GPG Usage Generating Key Pair To use GPG, first you must generate a key pair:\ngpg --generate-key Note: Use \u0026ldquo;gpg --full-generate-key\u0026rdquo; for a full featured key generation dialog.\nFollow prompts to choose: Key type (usually RSA is recommended for beginners). Key Size (2048 bits minimum; 4096 bits offer stronger security). Expiration Date (optional, but recommended). Your used ID information (name, email). A strong passphrase to protect your private key. List GPG Keys gpg -k #shows public keys | gpg --list-keys gpg -K #showw private keys | gpg --list-secret-keys Note: Use --keyid-format LONG to see more details of key IDs in long format.\nDelete GPG Keys --delete-keys (removes only the public key) --delete-secret-keys(removes only the private key) --delete-secret-and-public-keys (removes both public \u0026amp; private key) Example:\n$ gpg --delete-secret-and-public-keys \u0026#34;Test\u0026#34; gpg (GnuPG) 2.4.7; Copyright (C) 2024 g10 Code GmbH This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. sec ed25519/096719FFE9848B1D 2025-08-20 Test \u0026lt;test@mail.com\u0026gt; Delete this key from the keyring? (y/N) Y This is a secret key! - really delete? (y/N) Y pub ed25519/096719FFE9848B1D 2025-08-20 Test \u0026lt;test@mail.com\u0026gt; Delete this key from the keyring? (y/N) y Export Public Keys ~$ gpg -k [keyboxd] --------- pub ed25519 2025-08-20 [SC] [expires: 2028-08-19] B68B0C6CF2DCFA3528010218096719FFE9848B1D uid [ultimate] Test \u0026lt;test@mail.com\u0026gt; sub cv25519 2025-08-20 [E] [expires: 2028-08-19] Export using your \u0026ldquo;Name\u0026rdquo; or \u0026ldquo;Email\u0026rdquo;: gpg --armor --export \u0026#34;Test\u0026#34; #using name gpg --armor --export \u0026#34;test@mail.com\u0026#34; #using email Export using your GPG KeyID: # copy the code below the \u0026#34;pub\u0026#34; line gpg --armor --export B68B0C6CF2DCFA3528010218096719FFE9848B1D Note: --armor shows the public key in human readable format.\nImport Public Keys Import others public keys to your keyring to encrypt messages for them: # use this file: gpg --export \u0026#34;Test\u0026#34; \u0026gt; public_key.asc gpg --import public_key.asc Sign \u0026amp; Verify To Prove Authenticity gpg --sign file.txt #to sign as another private key owner gpg --default-key SIGNING_KEY --sign file.txt # replace SIGNING_KEY with EMAIL/NAME To check authenticity of a signed message. gpg --verify file.txt.gpg #to verify as another private key owner gpg --default-key \u0026#34;Test\u0026#34; --verify file.txt.gpg Encrypt \u0026amp; Decrpt #encrypt gpg -e -r \u0026#34;Recipient NAME or EMAIL or SIGNING_KEY\u0026#34; file.txt #decrypt gpg -d -r \u0026#34;Recipient NAME or EMAIL or SIGNING_KEY\u0026#34; file.txt.gpg \u0026gt; decrypted.txt Note: Using -r allows to you perform actions as another private key owner, otherwise it uses the default GPG key available in your system.\nThings To Know GPG Keyring A GPG Keyring is essentially a collection of database of public and private key that GPG stores and manages for you. It organizes and holds your keys for encryption, decryption, and signing operations.\nHow It Works? You can import keys into keyring from trusted sources or export keys to share.\nBasically, the public keys are frequently access and stored unencrypted since they are openly shared. Private keys are kept encrypted with your passphrase for security and stored separately to protect again unauthorized use. Keyring Components Public keyring:\nStores the public keys of your and others. These keys are used to encrypt messages or verify signatures. Stored in a file named pubring.kbx. Private keyring:\nStored your private keys, which are kept encrypted and protected. These keys allow you to decrypt messages and create digital signatures. Stored in folder named private-keys-v1.d. ","permalink":"https://docs.ayshell.dev/posts/gpg/gpg-101/","summary":"\u003ch1 id=\"what-is-gpg--pgp\"\u003eWhat is GPG / PGP?\u003c/h1\u003e\n\u003cp\u003eGnuPG (\u003cem\u003eaka GPG\u003c/em\u003e) is an implementation of standard known as PGP (\u003cem\u003ePretty Good Privacy\u003c/em\u003e). It uses a system of \u0026ldquo;Public\u0026rdquo; and \u0026ldquo;Private\u0026rdquo; keys for the encryption and signing of message or data.\u003c/p\u003e\n\u003ch2 id=\"private-key\"\u003ePrivate Key\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePrivate keys are the first half of a GPG key which is \u003cstrong\u003eused to decrypt messages\u003c/strong\u003e that are encrypted using public keys.\u003c/li\u003e\n\u003cli\u003eAlso used for signing messages - a way to prove that you own the key.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eObviously, you must not share the private keys anywhere\u003c/strong\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"public-key\"\u003ePublic Key\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePublic keys are the second half of a GPG key which is \u003cstrong\u003eused to encrypt messages\u003c/strong\u003e for the owner of private key.\u003c/li\u003e\n\u003cli\u003eIt is \u003cstrong\u003esafe to share it anywhere publicly\u003c/strong\u003e, as it can \u003cstrong\u003e\u003cem\u003eonly be used to encrypt\u003c/em\u003e\u003c/strong\u003e messages for the owner of the private key. In simple terms, owning just the public key is useless unless you own the private key.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003ch1 id=\"why-use-gpg\"\u003eWhy Use GPG?\u003c/h1\u003e\n\u003cp\u003eGPG (\u003cem\u003eGNU Privacy Guard\u003c/em\u003e) provides encryption and digital signing to:\u003c/p\u003e","title":"GPG: Beginner's Guide"},{"content":"What is SSH? SSH (Secure Shell) is a protocol used to securely access and manage remote systems over insecure networks. It\u0026rsquo;s widely used to log into remote Linux/Unis servers, transfers files, and run common across multiple machines.\nBasic SSH Concepts SSH Client Software on your computer that initiates the connection Example: terminal, Konsole, PuTTY, \u0026amp; more.\nSSH Server The remote computer you want to access; It listens for incoming SSH request and process them accordingly.\nAuthentication Most commonly done via passwords or cryptographic keys (recommended for security)\nHow SSH Authentication Works Password Authentication: Entering the actual password of the machine you want to access. Which less secure if you are entering the actual password and there\u0026rsquo;s a chance it might get compromised. Key-based Authentication: You create a key pair (private \u0026amp; public). The private key stays on your device and the public key goes on the server. It only lets you login if the keys match else there\u0026rsquo;s no prompt for password. It\u0026rsquo;s considered the most secure way to authenticate inside a machine. Where you enter the password for SSH key and additionally, it also checks for the private key in your machine as well. Add SSH Authentication In Servers It\u0026rsquo;s a simple task to enter ssh key authentication in the server you want.\nUsing ssh-copy-id tool (recommended) # uses the default ssh key available in your device ssh-copy-id username@remoteHost # uses the specific ssh key available in your device ssh-copy-id -i ~/.ssh/id_rsa.pub username@remoteHost Replace username@remoteHost with the server\u0026rsquo;s username and IP address.\nThe above command appends your public key to the ~/.ssh/authorized_keys file on the target server, creating directory/file and setting correct permissions automatically.\nManually add your public key cat ~/.ssh/id_rsa.pub | ssh username@remoteHost \u0026#34;mkdir -p ~/.ssh \u0026amp;\u0026amp; cat \u0026gt;\u0026gt; ~/.ssh/authorized_keys\u0026#34; This also appends your public key to the authorized list for SSH logins on the server\nFinally, try logging into the remote server and you will be prompted with the SSH key password rather than the actual password prompt for the remote device.\nSSH Keys in Linux Generate SSH Keys Most common algorithms are RSA or ED25519 ssh-keygen -t ed25519 -C \u0026#34;your_email@example.com\u0026#34; #prefer usign RSA for legacy systems ssh-keygen -t rsa -b 4096 -C \u0026#34;your_email@example.com\u0026#34; You\u0026rsquo;ll be prompted for a location to save the key; Press enter for default location or enter your custom location. The generated files will look like: Private key: ~/.ssh/id_ed25519 or ~/.ssh/id_rsa Public key: ~/.ssh/id_ed25519.pub or ~/.ssh/id_rsa.pub Listing SSH Keys Default SSH keys are stored inside ~/.ssh directory. You should see files like id_rsa, id_rsa.pub, id_25519, id_25519.pub and others like config: which stores the details of remote server for easy access and login. known_hosts: added by the ssh, list of connected remote host informations. Removing SSH Keys Delete a key pair (be cautious!) rm ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub This is enough to remove the ssh keys, there\u0026rsquo;s no need for additional commands to remove them.\nUpdating SSH Keys Simply run ssh-keygen again and choose to overwrite the existing key, or select a different filename for a new key. If you overwrite, old keys will not work for authentication anymore. You need to update the remote server\u0026rsquo;s authorized_keys with your new public key. To update SSH key on a remote server: ssh-copy-id -i ~/.ssh/new_id_25519.pub username@hostName Other Essentials About SSH Managing multiple keys: You can keep different key pairs and specify which one to use per server in your ./ssh/config. Securing your private key: Prefer using strong password, restrict file permission of private key to ensure only you can read it and never share the private key. SSH Login Connect using a specific private SSH key. ssh -i /path/to/privateKey username@hostName Connect to a specific IP as \u0026ldquo;username\u0026rdquo;. ssh \u0026lt;username\u0026gt;@hostName Change the \u0026lt;username\u0026gt; to the user you want to login as.\nRun a single command on the remote server without logging inside. iamyaash@fedora:~$ ssh zero-pi uptime Enter passphrase for key \u0026#39;/home/iamyaash/.ssh/id_\u0026lt;keyID\u0026gt;\u0026#39;: 14:52:27 up 2:27, 0 user, load average: 0.02, 0.01, 0.00 ","permalink":"https://docs.ayshell.dev/posts/ssh/ssh-101/","summary":"\u003ch1 id=\"what-is-ssh\"\u003eWhat is SSH?\u003c/h1\u003e\n\u003cp\u003eSSH (\u003cem\u003eSecure Shell\u003c/em\u003e) is a protocol used to securely access and manage remote systems over insecure networks. It\u0026rsquo;s widely used to log into remote Linux/Unis servers, transfers files, and run common across multiple machines.\u003c/p\u003e\n\u003ch1 id=\"basic-ssh-concepts\"\u003eBasic SSH Concepts\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003eSSH Client\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eSoftware on your computer that initiates the connection\n\u003cstrong\u003eExample\u003c/strong\u003e: \u003ccode\u003eterminal\u003c/code\u003e, \u003ccode\u003eKonsole\u003c/code\u003e, \u003ccode\u003ePuTTY\u003c/code\u003e, \u0026amp; more.\u003c/p\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003eSSH Server\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThe remote computer you want to access; It listens for incoming SSH request and process them accordingly.\u003c/p\u003e","title":"SSH: Beginner's Guide"},{"content":"Overview In general, building Docker images for any architecture involves creating container images that can run on different CPU architectures (like amd64, arm64, arm32, etc.). To build a Docker image for any architecture, you can use Docker buildx with cross-compilation support.\nEnsure QEMU is installed before proceeding:\nsudo dnf install qemu-user-static Architecture Syntax Docker architecture syntax generally follows this format,\nos/arch/variant os is the operating system, let\u0026rsquo;s use linux arch is the CPU architecture, such as: amd64 (x86_64) 386 (x86) arm64 (64-bit ARM) arm/v7 (32-bit ARM) Common example of architectures:\nlinux/amd64 - 64-bit Intel/AMD Linux linux/386 - 32-bit Intel/AMD Linux linux/arm64 - 64-bit ARM Linux (i,e Raspberry Pi) linux/arm/v7 - ARM 32-bit Linux Build the Image Build for a single architecture; Raspberry Pi Zero 2 W (i.e, 32-bit ARM) docker buildx build --platform linux/arm/v7 --tag name:tag . Build for multiple architectures; Desktop (x86_64), RPi 5 (arm64) and RPi Zero 2W docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --tag name:tag . Load the image to local Docker directly docker buildx build --platform linux/arm/v7 --output=type=docker --tag name:tag . Note: Using--output=type=docker loads the image into your local Docker directly (no push to registry).\nPush the image to a registry docker buildx build --platform linux/arm/v7 --tag name:tag --push . Note: If you want to push an image to a registry, use --platform with --push instead, skipping --output.\n","permalink":"https://docs.ayshell.dev/posts/docker/multi-arch-build/","summary":"A short guide to building and running container images for multiple architectures with instruction emulation.","title":"Docker: Build Multi-Architecture Container Images"},{"content":"Major Steps in Booting Sequence Stage Description BIOS/UEFI Initializes hardware components and POST to ensure system is ready to boot Bootloader (GRUB/etc) Loads Linux kernel and optional initramfs from disk into memory Kernel Initializes device drivers, mounts root filesystems, and starts PID 1 process Init/Systemd PID 1 lauches user-space services as defined by system configuration profiles. Runlevel/Target Configures and starts services as defined by system configuration profiles Login Presents users with login prompt or graphical interface Linux Booting Sequence The Linux booting sequence is a systematic process with distinct stages that prepare the operating system for user interaction.\n1. BIOS/UEFI Initialization: It checks whether the hardware components in your system are functional and ready to boot the operating system. Hardware components are keyboard, mouse, monitor, storage devices and etc.\nBIOS (Basic Input/Output System)\nIt can only use MBR (Master Boot Record). Using MBR limits the disk size to 2TB. Slower booting time. Less secure boot. UEFI (Unified Extensible Firmware Interface)\nUses GPT (GUID Partition Table) Offering faster booting time. Better security than BIOS. Breaks the 2TB limit and allows using more disk size. UEFI supports multiple bootloaders and fasters, more flexible booting. 2. POST (Power-On Self Test) POST is executed by the BIOS/UEFI firmware to verify that essential hardware components (RAM, CPU, keyboard, etc.) are functioning properly. If any issue is detected, an error is displayed or signaled using beep codes.\n3. Bootloader Execution After the BIOS/UEFI checks, now it needs to find and load up the bootloader software from the boot device\u0026rsquo;s MBR or EFI partition. The bootloader presents boots options and loads the selected Linux kernel and an optional initial RAM disk (initramfs).\nThe common bootloaders are GRUB2 or LILO. GRUB2 is most fully features and widely used today. It can handle booting multiple operating sytems. Apart from that, it provides more features such as looks, graphical changes and some power-user specific features as well.\nThe system firmware (BIOS/UEFI) checks the configured boot order and loads the bootloader (e.g., GRUB2) from the appropriate device.\nIn simple terms, the bootloader locate the operating system kernel on the disk, load the kernel into memory and start the kernel\n4. Kernel Initialization The Linux kernel is loaded into memory after Bootloader, decompresses itself, initializes hardware(via device drivers), and mounts the root file system.\nOnce the bootloader loads the kernel into memory, the kernel takes over the computer\u0026rsquo;s resources and starts initializing all the background processes and services.\nFirst, it decompresses itself into the memory. Checks the hardware and loads device drivers and other kernel modules. Next, the kernel start the PID 1 process (i.e, Systemd/SysV..) aka init process. 5. Init/Systemd Launch The first user-space process started by the kernel is assigned PID 1. On modern systems, this is typically systemd, which takes over as the init system and launches other services.\n6. Runlevel/Target Process The systemd uses target configuration files to decide which mode it should be booting into, such as multi-user.target for text only or graphical.target for UI based.\nThings to Know Master Boot Record (MBR) The MBR is the first sector of a hard disk or any storage device.\nIt stores three things:\nBootloader Code (446 Bytes) Partition Table (64 Bytes, for upto 4 partitions) MBR Signature (2 Bytes) When a computer starts, the BIOS looks for the MBR, loads its bootloader code into memory, and uses it\u0026rsquo;s partition information to find and start the operating system. MBR is essential for booting traditional BIOS-based systems, and the OS cannot load without it. However, it can only handle disks up to 2TB. Allows upto 4 primary partitions per disk. BIOS boots from MBR The firmware looks for the MBR, at the very first sector of the boot disk. The MBR contains small bootloader code and partition table. This code launches the full bootloader (GRUB2), which then loads the Linux kernel into memory. GUID Partition Table (GPT) It was created as part of the UEFI specification, replacing the older MBR system. GPT is a modern standard for organizing partition tables on storage devices like hard drives and SSDs.\nIt supports large drives than MBR; theoretically up to 9.4ZB. Allows upto 128 partitions per disk. Stores the partition table at both the start and end of the disk for backup, improving reliability against corruption UEFI boots from EFI System Partition (ESP) UEFI looks for a special FAT32-formatted partition called the EFI System Partition on disks usually formatted with GPT. This partition contains EFI executable files like bootloaders that UEFI loads directly. ","permalink":"https://docs.ayshell.dev/posts/linux/boot/linux-booting-sequence/","summary":"High-level explanation of how the Linux is booted.","title":"Linux: Booting Process"},{"content":"Linux Package Management When managing software pacakge on Linux systems, it\u0026rsquo;s important to understand the distinction between low-level and high-level package management tools.\nLow-Level Tool: Direct Package Operations This commands interacts directly with RPM package files, allowing users to perform basic package operations independent of online repositories or additional dependency handling.\nKey Characteristics:\nNo automatic dependency resolution. Operates solely on local .rpm files or installed packages. Suitable for advanced users or situations requiring precise control. High-Level Tool: Handling Repositories and Dependency Management These tools build on top of basic capabilities of rpm/dpkg and add robust package management features. Key Characteristcs:\nKeeps logs (transaction history)of installs, removals, and updates, enabling rollback when needed. Search, enable or disable software repositories as software sources. Update all or specific packages with a single command, pulling updates from repositories. Detect and resolve package repositories, fetching any required additional packages from configured repositories. Automatically download from repositories instead of using local packages. Install a Pacakge Using Local Package Tool rpm Package Manager rpm tool is used for handling package operations using an .rpm file\nsudo rpm -i dummy-1.0.0-1.x86_64.rpm dummy: The software package name. 1.0.0: Version of packaged software. 1: The number of times this software version has been packaged; increments each time for packaging or rebuiding changes. (first packaging/build iteration of this version) x86_64: The hardware architecture. dpkg Package Manager dpkg tool is used for handling package operations in Debian based distros.\nsudo foo_1.0-1_amd64.deb Using Package Manager Package managers such as dnf or yum automatically pulling packages from repositories to install.\nsudo dnf install dummy #for rpm-based sudo apt install dummy #for deb-based dnf/apt install package_name is enough to download and install the package. They automatically resolve and install dependencies by pulling packages from online repositories, in case it needs to install dependencies.\nUpgrade a Package Using Local Package Tool 1. rpm Package Manager\nUpgrade to a new version (or) install the package if not present.\nrpm -Uvh dummy-1.1.0-1.x86_64.rpm Ensure you have the same package name with different versions. dpkg Package Manager Use -i flag to install, overwriting, and upgrading package.\ndpkg -i foo_1.1.0-1_amd64.deb Using Package Manager sudo dnf update sudo apt update It updates the existing package in the system with the updated one, and it also handles dependencies automatically. Especially, there\u0026rsquo;s no need to reboot to apply the changes across the system.\nRemove a Pacakge Using Local Package Tool 1.rpm Package Manager\nsudo rpm -e package_name Erase (remove) package by name. If multiple matches exist, use --allmatches. 2. dpkg Package Manger\nsudo dpkg -r package_name Removes a package, but leaves configuration files. sudo dpkg -P package_name # or sudo dpkg --purge package_name Purges the pacakge and removes configuration files as well. Using Package Manager #rpm sudo dnf remove package_name # deb sudo apt remove pacakge_name sudo apt purge package_name Query a Package Using Local Package Tool RPM Command DEB Command Purpose rpm -q foo dpkg -s foo or dpkg-query -W foo Query if a package is installed rpm -qa dpkg -l or dpkg-query -W List all installed packages rpm -ql foo dpkg -L foo List all files from installed package rpm -qc foo dpkg -L foo | grep /etc Show configuration files of installed package (by convention under /etc) rpm -qd foo dpkg -L foo | grep /doc Show documentation files (typically in /usr/share/doc) rpm -qf /usr/bin/foo dpkg -S /usr/bin/foo Find which package owns a file rpm -qpi foo.rpm dpkg-deb -I foo.deb Show information about the DEB file rpm -qpl foo.rpm dpkg-deb -c foo.deb List the available files in DEB file rpm -qR foo dpkg -s foo or apt-cache depends foo List dependencies of package Notes:\nThe apt-cache depends foo command is often used for querying dependencies in APT-based systems. Configuration files and documentation location conventions may vary by package, but are usually under /etc and /usr/share/doc respectively. Both dpkg and dpkg-query can be used for querying the DEB database; apt and apt-cache are higher-level tools. Using Package Manager #for queries on package dependencies and repo info #RPM based sudo dnf info package_name #Debian based sudo apt show package_name sudo apt-cache depends sudo apt-cache rdepends Verifying a Pacakge RPM-based Systems Command Purpose rpm -V foo Verify files by package against RPM database rpm -Va Verify all installed packages rpm -Vf /path/to/file Verify package that owns the given file rpm -Vp foo.rpm Verify package integrity against .rpm file (not installed) rpm --checksig foo.rpm Check GPG/MD5 signature and integrity; prior to install rpm -K path/to/file Check GPG/MD5 signature and integrity; prior to install rpm --checksig verifies the authenticity and integrity of RPM file before installation rpm -V checks that files installed match what\u0026rsquo;s recorded in RPM database. rpm -Vp can verify a package file against itself; doesn\u0026rsquo;t require installation. Debian-based Systems Command Purpose debsums foo Verify installed files for a package; uses md5sums dpkg -V foo Verify installed files for a package; slower, as it compares file checksums, permissions dpkg-sig --verify foo.deb Verify PGP/GPG signature of a .deb file; not installed, package file authenticity debsums is the most common tool for verifying checksums of installed files. dpkg-sig --verify checks signatures for package files. Clean-Up and Maintenance RPM (dnf) DEB (apt) Purpose dnf autoremove apt autoremove Remove orphaned (unused) packages dnf clean all apt clean Clear cached package files to free disk space apt autoclean Similar to apt clean but like autoremove Transaction Management Rollback and History (dnf/yum) Purpose Command Description View transaction history dnf history Lists all past package install, update, and remove operations (transactions) Undo a past transaction dnf history undo Reverts a specific transaction, restoring the system to its previous state Rollback to a previous state dnf history rollback Rolls back the system to the state immediately after the given transaction Why this is useful: Transaction history lets you track all changes made to your system by dnf or yum. undo and rollback allow you to reverse package updates or removals easily, which is very helpful when troubleshooting or recovering from a problematic change. Example Workflow: See transaction history: sudo dnf history list If you spot a problematic update (e.g., with ID 25), undo just that transaction: sudo dnf history undo 25 Or, to roll back all changes up to just after transaction 22: sudo dnf history rollback 22 Note:\nTransactions are listed with unique IDs. yum (on older systems) supports similar commands: yum history, yum history undo, yum history rollback. Miscellaneous Operations These are the questions, that I got when I started experimenting with package managements, so let me write this in my own terms.\n1. What would you do if you get any error such as \u0026ldquo;package is already installed\u0026rdquo;, but you want to reinstall it anyway?\nUse --replacepkgs to Install the packages even if some of them are already installed on this system Use --replacefiles to Install the packages even if they replace files from other, already installed, packages. Use --force to aggressively install the package, which combines --replacepkgs and --replacefiles. sudo rpm -ivh --replacepkgs hayase-6.4.13-1.fc42.x86_64.rpm sudo rpm -ivh --replacefiles hayase-6.4.13-1.fc42.x86_64.rpm # replace files #or aggrevise reinstall sudo rpm -ivh --force hayase-6.4.13-1.fc42.x86_64.rpm For dnf:\nsudo dnf reinstall package 2. How do you resolve a broken package dependency?\nIn Debian:\nsudo apt-get install -f #or sudo apt --fix-broken install In RPM:\n#to fix broken dependencies sudo dnf check #check for problems in package database sudo dnf check-upgrade #to fix issues sudo dnf distro-sync 3. Manage Package Repositories\nIn RPM based: This follows a different approach by installing a .rpm file:\nTerminal command:\nsudo dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm sudo dnf install https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm After the installation, the repository will be added under /etc/yum.repos.d and you verify it by using ll /etc/yum.repos.d. In Debian based: This is the traditional way of adding a new package repositories to Debian Linux.\nThe available repositories are listed in sources.list under /etc/apt. Open the file in editor of your choice:\nsudo nvim /etc/apt/source.list Now we can add the repository here, by following this syntax:\ndeb [repo URL] [distribution] [component(s)] Lastly, update to make the changes take effect:\nsudo apt update 4. What are Held and Pinned packages?\nHeld packges are configured to NOT be automatically upgraded by the system package manager during the routine updates.\nThis keeps them locked at their current version until it\u0026rsquo;s manually updated. Debian based: #using high level tool sudo apt-mark hold btop #hold the packge apt-mark showhold # list all the hold packages sudo apt-mark unhold btop #unhold the package #using low level tool dpkg --get-selections | grep hold # to list dpkg --get-selections | grep install Pinned packages refers to controlling which package version is installed or kept by specifying rules, typically using the APT preferences system.\nPinning can select specific versions, repositories, or releases as the source for certain pacakges, and can also prevent upgrades. RPM based: Install dnf-plugins-core package\nsudo dnf versionlock add btop # add btop to versionlock list sudo dnf versionlock list # list version-locked packages sudo dnf versionlock delete btop # remove btop from versionlock list ","permalink":"https://docs.ayshell.dev/posts/package/management/","summary":"Essential package management and real world examples that cover all fundamental operations for managing RPM/DEB packages.","title":"Package Management"},{"content":"What is LVM? LVM is a special tool in Linux that let\u0026rsquo;s you manage disk storage in much more flexible way than traditional partitions.\nThink of it as turning multiple hard drives into a big, flexible stroage pool that you can split, resize, or grow whenever you want, without worrying about the limits of classic disk partitions.\nWhy Use LVM? Resize storage easily: You can expand or shrink volumes without reformatting or losing data. Combine multiple disks: Make many drives look like one big storage area. Add more space anytime: Plug in new hard drive and add its space instantly. Move or migrate data: Shift storage between drives with little downtime. Take snapshots: Save the exact state of you data at a moment in time, which helps with backups. Practical Example Classic Partitioning (without LVM) You have 100GB disk with /home and /var partitions. /home fills up, while /var has lots of free space. Problem: You can\u0026rsquo;t take space from /var and give it to /home without migrating, deleting, repartitioning or copying data aroud. Which is possible but risky and time-consuming. With LVM Let\u0026rsquo;s say you have two physical disks:\nDisk 1: 100GB Disk 2: 200GB You do the following:\nInitialize the disks as LVM Physical Volume (PV). Combine them into a Volume Group (Vg); Eg: testvg, making it a single 300GB storage pool. Create Logical Volume inside that pool, for example: lv_home for your /home directory: 150GB. lv_var for your /var directory: 50GB. If /home is getting full, you can:\nShrink lv_var to 25GB (only if it has enough space). Grow lv_home to 175GB. To add more space in the future:\nPlug in a new disk. Add it to the volume group, after making a physical volume out of it. Instant make the space available to any logical volume you choose. Basic Usage Physical Volume (PV) : Disk/Partition initialized for LVM Volume Group (VG) : Pool for combining several Physical Volumes (PVs). Logical Volume (LV): Carved-out \u0026ldquo;Virtual Partition\u0026rdquo; for filesystems. List Information Physical Volume (PV):\nsudo pvs Volume Group (VG):\nsudo vgs Logical Volume (LV):\nsudo lvs Create PV, VG \u0026amp; LV Physical Volume (PV):\nsudo pvcreate /dev/sda #if only one disk sudo pvcreate /dev/sda /dev/sdb #if more than one disk Volume Group (VG):\nsudo vgcreate \u0026lt;VG_NAME\u0026gt; /dev/sda #if only one physical volume to add Logical Volume (LV):\nsudo lvcreate -n \u0026lt;LV_NAME\u0026gt; -L 8G \u0026lt;VG_NAME\u0026gt; Remove PV, VG \u0026amp; LV Physical Volume (PV):\nsudo pvremove /dev/sda #if only one disk sudo pvremove /dev/sda /dev/sdb #if more than one disk Volume Group (VG):\nsudo vgremove \u0026lt;VG_NAME\u0026gt; Logical Volume (LV):\nsudo lvremove /dev/\u0026lt;VG_NAME\u0026gt;/\u0026lt;LV_NAME\u0026gt; #example sudo lvremove /dev/allvg/lv_home Modifying Storage Size Extending an LVM Logical Volume (No Downtime, Safe) Check available space in the volume group and decide the amount to extend the size. sudo vgs sudo vgdisplay # for more detail Extend the logical volume (lv_home) Add 2GB sudo lvextent -L +2G /dev/allvg/lv_home Modern LVM also supports percentage sudo lvextend -l +100%FREE /dev/allvg/lv_home Resize the filesystem after the extending the volume group sudo resize2fs /dev/allvg/lv_home # do this while it\u0026#39;s mounted Note:resize2fs simply updates the metadata and structure to reflect the bigger Logical Volume after a resize.\nNote: Filesystem can be grown while mounted for ext4/xfs\nBasically, the space is coming from the volume group (allvg), so I\u0026rsquo;m using vgdisplay to check the available Free PE/Size. Then, we can use lvextend -L +2G ... to extend the space based on the Free PE/Size you have. Lastly, use resize2fs to update the partition table. Output of vgdisplay:\niamyaash@pi5:~ $ sudo vgdisplay --- Volume group --- VG Name allvg System ID Format lvm2 Metadata Areas 1 Metadata Sequence No 2 VG Access read/write VG Status resizable MAX LV 0 Cur LV 1 Open LV 1 Max PV 0 Cur PV 1 Act PV 1 VG Size \u0026lt;8.00 GiB PE Size 4.00 MiB Total PE r 2047 Alloc PE / Size 1024 / 4.00 GiB Free PE / Size 1023 / \u0026lt;4.00 GiB VG UUID 4KP5xQ-icGT-1G0L-hr8S-2oMc-1cuQ-y71xAz Shrinking an LVM Logical Volume (Caution!) Reducing a volume is riskier, always backup before you do anything!\nUnmount the filesystem, because it\u0026rsquo;s not possible to shrink while it\u0026rsquo;s mounted: sudo umount /mnt/lv_home Perform a forced filesystem check (mandatory): sudo e2fsck -f /dev/allvg/lv_home Shrink the filesystem Reduce to 4GB Total Size sudo resize2fs /dev/allvg/home 4G Reduce the Logical Volume: sudo lvreduce -L 4G /dev/allvg/lv_home Note: Never reduce the LV before shrinking the filesystem.\nRemount and verify: sudo mount /dev/allvg/lv_home df -h /mnt/lv_home How to Initialize a Disk with LVM Ensure you format the disk, and prepare it for partitioning: lsblk #list the block of partitions sudo mkfs.ext4 /dev/sda #ext4 format Create Partition Using parted: sudo parted /dev/sda mklabel gpt #set partition table to GPT mkpart primary ext4 1MiB 80GiB #create 8GB partition name 1 gpt_home #set partition label quit # save/write the chages for partitions Note: Make sure to use ext4, as it is most recommended format.\n# list the available partitions lsblk To Remove the Partition:\nsudo parted /dev/sda rm 1 #to remove the partition number 1 (i.e: sda1) Create Physical Volume sudo pvs # list any avail PVs sudo pvdisplay # more details sudo pvcreate /dev/sda1 # select the sda1 which is the 80GB partition Create Volume Group sudo vgs sudo vgdisplay sudo vgcreate allvg /dev/sda1 # create a new VG name and select the partition as well Create Logical Volume sudo lvs # list the available LVs sudo lvdisplay sudo lvcreate -n lv_home -L 44G allvg # create 44GB LV with LV name as lv_home Scan the disk for LVM usage:\nsudo lvmdiskscan Format the LV (Virtual Partition) as ext4:\nsudo mkfs.ext4 /dev/allvg/lv_home Mount Logical Volume sudo mkdir /mnt/lv_home sudo mount /dev/allvg/lv_home /mnt/lv-home Mount Automatically At Boot lsblk -f # list partition blocks along with other information such as UUID # or blkid | grep dev/sda # to see all UUIDs Locate the UUID of you logical volume, especially note the ext4 format UUID not the LVM_Member.\nsudo nano /etc/fstab Add this line into /etc/fstab:\nUUID=44bbb6b2-803e-4009-b8f5-e4fbcd743aff /mnt/lv_home ext4 defaults 0 2 How to Fully Reinitialize a Disk (In case you messed up) Ensure your disk is not mounted or used by your operating system, because these steps destroy all data on the disk(s) involved.\nUnmount Logical Volumes, if mounted: sudo umount /mount/point Remove Logical Volume (LV) # list the available LVs sudo lvs # remove the selected LV sudo lvremove /dev/\u0026lt;VG_NAME\u0026gt;/\u0026lt;LV_NAME\u0026gt; Remove the Volume Group (VG) # list the available VGs sudo vgs # remove the selected VG sudo vgremove \u0026lt;VG_NAME\u0026gt; Remove the Physical Volume (PV) # list the available PVs sudo pvs # remove the PV sudo pvremove /dev/sdX Substitute /dev/sdX with your partition name where the PV is created.\nRemove Partitions To Start Fresh Use tools like mkfs to format and fdisk or parted to create partitions.\n","permalink":"https://docs.ayshell.dev/posts/linux/file-systems/lvm/","summary":"\u003ch1 id=\"what-is-lvm\"\u003eWhat is LVM?\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003eLVM\u003c/strong\u003e is a special tool in Linux that let\u0026rsquo;s you manage disk storage in much more flexible way than traditional partitions.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eThink of it as turning multiple hard drives into a big, flexible stroage pool that you can split, resize, or grow whenever you want, without worrying about the limits of classic disk partitions\u003c/em\u003e.\u003c/p\u003e\n\u003ch1 id=\"why-use-lvm\"\u003eWhy Use LVM?\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eResize storage easily\u003c/strong\u003e: You can expand or shrink volumes without reformatting or losing data.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCombine multiple disks\u003c/strong\u003e: Make many drives look like one big storage area.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAdd more space anytime\u003c/strong\u003e: Plug in new hard drive and add its space instantly.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMove or migrate data\u003c/strong\u003e: Shift storage between drives with little downtime.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTake snapshots\u003c/strong\u003e: Save the exact state of you data at a moment in time, which helps with backups.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"practical-example\"\u003ePractical Example\u003c/h1\u003e\n\u003ch2 id=\"classic-partitioning-without-lvm\"\u003eClassic Partitioning (without LVM)\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eYou have 100GB disk with \u003ccode\u003e/home\u003c/code\u003e and \u003ccode\u003e/var\u003c/code\u003e partitions.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/home\u003c/code\u003e fills up, while \u003ccode\u003e/var\u003c/code\u003e has lots of free space.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProblem\u003c/strong\u003e: You can\u0026rsquo;t take space from \u003ccode\u003e/var\u003c/code\u003e and give it to \u003ccode\u003e/home\u003c/code\u003e without migrating, deleting, repartitioning or copying data aroud. \u003cem\u003eWhich is possible but risky and time-consuming\u003c/em\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"with-lvm\"\u003eWith LVM\u003c/h2\u003e\n\u003cp\u003eLet\u0026rsquo;s say you have two physical disks:\u003c/p\u003e","title":"What is LVM (Logical Volume Manager) and Why Use it?"},{"content":"Environment Variables In Linux, Environment variables are named key-value pairs that store information about your operating environment and configuration. They are crucial because they let the operating system, applications, and scripts know about elements such as :\nWhere programs are location; _via _PATH. Your user/currently logged-in directory; HOME. Language or locale settings. System-wide or app-specific configurations. In simple terms, environment variables are a foundational way that Linux customizes, configues, and manages the actions of programs and users through simple \u0026ldquo;key=value\u0026rdquo; pairs.\n1. Structure Each environment variable has a name (usually all-uppercase by convention, like PATH, HOME, EDITOR) and a value (a string or set of strings).\nSyntax:\nNAME=value Example:\nPATH=/usr/local/bin:/usr/bin:/bin HOME=/home/iamyaash You can see that we are separating directory location using : colon.\n2. Purpose Customization: Set your preferred editor, default shell, time zone, etc. Application Configuration: Programs often check environment variables for things like database passwords or settings. System Management: Admins set global variables to manage environment settings for all users. Dynamic Context: Environments variables adapt applications to different users, folders or hardware settings. Eg: Try running this command echo $HOME with different users, and you will see different output each time. 3. Types System Environment Variables: Affect all users and entire system. Set in files like /etc/environment or /etc/profile. User Environment Variables: Affect only user session. Typically set in ~/.bashrc, ~/.profile, etc. Session Variables: Exist only for the life of current terminal/session. Persistent Variables: Remain across reboots/sessions because they are defined in configuration files. Read-Only Variables: Cannot be changed after being set in a session. 4. Usage Programs and the shell read these variables to determine settings like which directories to search for command ($PATH), where your home folder is (HOME), or what language to use (LANG).\nNote: You can see your environment variables with commands like printenv, env, or set.\n5. Features Values are case-sensitive and, by convention, variable names are ALL CAPS. Some variables, like PATH, use colons (:) to separate multiple values. Environment variables are inherited by child processes, making them essential for scripts and subprocesses. Common Environment Variables Variable Value Usage PATH /usr/local/bin:/usr/bin/:/bin List of directories to search for executables HOME /home/iamyaash Current user\u0026rsquo;s home directory SHELL /bin/bash User\u0026rsquo;s preferred shell USER iamyaash Current username LANG en_US.UTF-8 Language/locale settings EDITOR vim Default text editor ","permalink":"https://docs.ayshell.dev/posts/linux/environment-variables/","summary":"\u003ch1 id=\"environment-variables\"\u003eEnvironment Variables\u003c/h1\u003e\n\u003cp\u003eIn Linux, \u003cstrong\u003eEnvironment variables are named key-value pairs\u003c/strong\u003e that store information about your operating environment and configuration. They are crucial because they let the operating system, applications, and scripts know about elements such as :\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eWhere programs are location; _via _\u003ccode\u003ePATH\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eYour user/currently logged-in directory; \u003ccode\u003eHOME\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eLanguage or locale settings.\u003c/li\u003e\n\u003cli\u003eSystem-wide or app-specific configurations.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cem\u003eIn simple terms, \u003cstrong\u003eenvironment variables\u003c/strong\u003e are a foundational way that Linux customizes, configues, and manages the actions of programs and users through simple \u0026ldquo;key=value\u0026rdquo; pairs.\u003c/em\u003e\u003c/p\u003e","title":"Linux Environment Variables"},{"content":"mail Local notifications via mail spool (typically for system messages or scripts). It provides simple email interface for users on the same system.\nCheck Mail\nmail It lists the mail by reading your spool file in /var/mail/\u0026lt;username\u0026gt;.\nUseful mail commands at the \u0026amp; promt\n8 - Read a specific message number; 1-n. d - Delete the current message | current read message q - Quit and save your read mail; moves read messages out of your inbox n - Reads the next message p - Print the current message; re-read the mail h - Show the message headers list. Send Mail to Another User\necho \u0026#34;This is body when using this command\u0026#34; | mail -s \u0026#34;Subject\u0026#34; iamyaash echo \u0026#34;Backup completed successfully.\u0026#34; | mail -s \u0026#34;Backup Status\u0026#34; adminuser df -h | mail -s \u0026#34;Disk Usage Report:\u0026#34; iamyaash You can also use just mail username, then type a subject and body, finishing it with CTRL+D.\nwall Display a message to all the currently logged in users. It\u0026rsquo;s mostly used for quick system-wide announcements and only root or users with elevated privileges can broadcast.\nBroadcast a message\nSingle line message:\nwall \u0026#34;This system will reboot in 8 minutes.\u0026#34; Multi-line message:\nwall \u0026lt;type your message\u0026gt; (Press CTRL+D to send \u0026amp; exit) write It sends real-time messages to another user who is currently logged-in on the same system. Both uses must be logged in, since it\u0026rsquo;s a real-time messaging tool it won\u0026rsquo;t store the message for reading it later. In simple terms, it\u0026rsquo;s not persistent like mail.\nCan estalish communication only when the two users are online at the same time.\nFind who is logged in\nwho # to see who is currently logged-in w # see wee what they are doing Send a message\nwrite iamyaash Throw an error, when the user who is sending the message don\u0026rsquo;t have elevated privileges:\niamyaash@pi5:~ $ write hugo-pages pts/1 write: effective gid does not match group of /dev/pts/0 Make sure to use sudo, when lacking privileges:\n# sender iamyaash@pi5:~ $ sudo write hugo-pages pts/1 this is testing! # receiver hugo-pages@pi5:~ $ Message from iamyaash@pi5 (as root) on pts/2 at 00:22 ... this is testing! EOF ","permalink":"https://docs.ayshell.dev/posts/linux/communications/wall-write-mail/","summary":"Use mail to send or receive stored messages \u0026amp; system notificaitons, wall to broadcast announcements to all users and use write for quick direct messages to another user.","title":"Linux Messaging Basics: mail, wall \u0026 write"},{"content":"Regular Expression Regular expression is a method of pattern matching. It allows you to define patterns of texts and search for it in other texts, no matter the complexity or the amount of text there is to process.\nUsing regular expression is considered a more efficient solution, when there\u0026rsquo;s complexity in searching for a text that you want to find. It is also called as regex.\nKeep in mind that regular expression is supported in almost every programming language. If you were to face a situation when there\u0026rsquo;s complexity in searching a text, take a look at how the systax looks like other programming languages and utilize them.\nGetting Started with Regular Expressions Learning the fundamentals before diving into the advanced areas will help you grasp the concept.\n1. Literal Strings This is a simple and a straightforward matching, that it simply matches \u0026ldquo;hello\u0026rdquo; with \u0026ldquo;hello\u0026rdquo;. This is yet another way to using regex, but a simple search as well.\n2. Metacharacters It uses special characters(symbols other than alpha-numeric) and each gives a special meaning in regular expression.\n. = Dot\nMatch any single character; It must include any single character. h-y = hey or hoy or huy\u0026hellip; ^ = Caret\nAka Anchor. It matches any string that starts with ^. Eg: ^abc - It looks for string that starts with abc. $ = Dollar Sign\nIt matches any string that ends with $. Eg: abc$ - It looks for string that ends with abc. * = Asterisk\nIt matches zero or more string; It can skip matching characters Eg: he* = hey, hello, heat\u0026hellip; It can match any number of characters that starts after he.... In case, it can\u0026rsquo;t match any, it will look for he only, since * it\u0026rsquo;s not necessary to add a character anyway. + = Plus Sign\nIt matches one or more characters; Similar to . (dot), but it must match atleast one character. Eg: +uck = luck, duck, suck(atleast one) || gluck(more than one) ? = Question Sign\nIt matches zero or one character; Similar to . (dot), but it can skip matching Eg: lie? = lied (atmost one) || lie (zero) | = Pipe Sign\nIt matches characters separated by | pipe symbol. Eg: cat|dog = Matches either cat or dob; Similar to OR gate or operator. () = Paranthesis\nIt match all characters that enclosed within it; Order of character matters. Eg: (abc|def) = Match abc or def; This is most commonly used for combining with other metacharacters when searching for texts. 3. Special Sequences Special sequences are used to enhance the pattern matching by providing matching patterns logic and consist of \\ (backslash) and alphabetical characters\nUsing backslash followed by a character, we can mention the pattern matching logic.\nSymbol Meaning Character Class / Description \\b Matches a word boundary (start or end of a word) — \\B Matches not at a word boundary — \\w Matches any word character [a-zA-Z0-9_] \\W Matches any non-word character [^a-zA-Z0-9_] \\d Matches any digit [0-9] \\D Matches any non-digit [^0-9] \\s Matches any whitespace character [ \\t\\n\\r\\f\\v] \\S Matches any non-whitespace character [^ \\t\\n\\r\\f\\v] \\n Matches a newline character — \\f Matches a form-feed character — \\t Matches a tab character — \\v Matches a vertical tab character — $ Matches at the end of a string — ^ Start of line/string Start of any line (multi-line) $ End of line/string End of any line (multi-line) \\A Start of string Only very beginning of string \\Z End of string Only very end of string Notes:\nIn regular expressions, ^ and $ are used for matching the start and end of a string, not A and Z. (as far as I know) The backslash (\\) is required for escape sequences like \\b, \\d, etc. [a-zA-Z0-9_] is the character class for word characters (\\w). [ \\t\\n\\r\\f\\v] is the character class for whitespace (\\s). 4. Character Classes In simple terms, Character Classes helps finding set of characters easily. The charactes are enclosed within a square bracket[].\nCharacter Class Description [abc] Matches the letter a/b/c [abc][xz] Match letter a/b/c followed by either x/z [^abc] Match all letters except a/b/c. [0-9] Match all digits from 0-9 (inclusive range) [a-z] Match any lowercase letters [A-Z] Match any uppercase letters [a-zA-Z] Match lowercase/uppercase letters [a-zA-Z0-9_] Match any alphanumeric character [m-p2-8] Ranges between m-p letters and 2-8 numbers 5. Occurrence Indicators Some of the metacharacters are also considered as occurence indicators. It plays the vital role in determining the occurences of characters.\nThis is the basic occurence indicators:\nOccurrence Indicators Description + Matches one or more ? Matches zero or one * Matches zero or more These are some advanced that uses curly braces {}:\nOccurrence Indicators Description {n} Matches exactly n number of times {n,} Matches at atleast n number of times {n,m} Matches from n to m times {,n} Matches upto n times References:\nhttps://towardsdatascience.com/the-essentials-of-regular-expressions-b52af8fe271a/ https://mahabub-r.medium.com/mastering-regular-expressions-the-ultimate-guide-from-basics-to-advanced-techniques-ffb6a7ffd564 https://pynative.com/python-regex-special-sequences-and-character-classes/ ","permalink":"https://docs.ayshell.dev/posts/regex/regex-basics/","summary":"\u003ch1 id=\"regular-expression\"\u003eRegular Expression\u003c/h1\u003e\n\u003cp\u003eRegular expression is a \u003cem\u003emethod of pattern matching\u003c/em\u003e. It \u003cstrong\u003eallows you to define patterns of texts and search for it in other texts\u003c/strong\u003e, no matter the complexity or the amount of text there is to process.\u003c/p\u003e\n\u003cp\u003eUsing regular expression is considered a \u003cem\u003emore efficient solution, when there\u0026rsquo;s complexity in searching for a text\u003c/em\u003e that you want to find. It is also called as \u003cstrong\u003eregex\u003c/strong\u003e.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eKeep in mind that regular expression is supported in almost every programming language. If you were to face a situation when there\u0026rsquo;s complexity in searching a text, take a look at how the systax looks like other programming languages and utilize them.\u003c/p\u003e","title":"Fundamentals of Regular Expressions"},{"content":"Debian Package File Structure A Debian pacakge (.deb) is an archive that contains all the files necessary to install a software applicaiton on a Debian-based system. It includes executable files, libraries, documentation and metadata about the package.\nInternal Structure of a Debian Package A .deb pacakge is essentially a tar archive that contains three main files:\ndebian-binary: A text file contains the version of standard packaging format. (as of now, it\u0026rsquo;s 2.0) control.tar.gz: It contains the metadata, and other maintainer scripts. In simple terms, it contains all the information about the pacakge but the main source. data.tar.gz: It contains the actual files of the softwarte to be installed in a Debian based system. Structure of debian/ Directory iamyaash@pi5:~/testBuild/hello-1.0/debian $ ll total 96K -rw-r--r-- 1 iamyaash iamyaash 186 Jul 6 14:45 changelog -rw-r--r-- 1 iamyaash iamyaash 528 Jul 6 14:45 control -rw-r--r-- 1 iamyaash iamyaash 1.9K Jul 6 14:45 copyright -rw-r--r-- 1 iamyaash iamyaash 138 Jul 6 14:45 hello-1.0.cron.d.ex -rw-r--r-- 1 iamyaash iamyaash 537 Jul 6 14:45 hello-1.0.doc-base.ex -rw-r--r-- 1 iamyaash iamyaash 28 Jul 6 14:45 hello-1.0-docs.docs -rw-r--r-- 1 iamyaash iamyaash 1.6K Jul 6 14:45 manpage.1.ex -rw-r--r-- 1 iamyaash iamyaash 3.8K Jul 6 14:45 manpage.md.ex -rw-r--r-- 1 iamyaash iamyaash 4.6K Jul 6 14:45 manpage.sgml.ex -rw-r--r-- 1 iamyaash iamyaash 11K Jul 6 14:45 manpage.xml.ex -rw-r--r-- 1 iamyaash iamyaash 962 Jul 6 14:45 postinst.ex -rw-r--r-- 1 iamyaash iamyaash 935 Jul 6 14:45 postrm.ex -rw-r--r-- 1 iamyaash iamyaash 695 Jul 6 14:45 preinst.ex -rw-r--r-- 1 iamyaash iamyaash 882 Jul 6 14:45 prerm.ex -rw-r--r-- 1 iamyaash iamyaash 176 Jul 6 14:45 README.Debian -rw-r--r-- 1 iamyaash iamyaash 261 Jul 6 14:45 README.source -rwxr-xr-x 1 iamyaash iamyaash 690 Jul 6 14:45 rules -rw-r--r-- 1 iamyaash iamyaash 538 Jul 6 14:45 salsa-ci.yml.ex drwxr-xr-x 2 iamyaash iamyaash 4.0K Jul 6 14:45 source drwxr-xr-x 2 iamyaash iamyaash 4.0K Jul 6 14:45 upstream -rw-r--r-- 1 iamyaash iamyaash 1.2K Jul 6 14:45 watch.ex The *.ex files are for example, you can take a look at it understand what to do next. But we can delete them rm *.ex.\ncontrol The control file is the heart of Debian package\u0026rsquo;s metadata. It tells the package manager everything it needs to know about the package. Such as package name, version, license, description, summary and etc.\nAn example of control file in Debian\nPackage: appName Version: 8.8.80 License: unknown Vendor: Yashwanth Rathakrishnan Architecture: amd64 Maintainer: Yashwanth Rathakrishnan Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libsecret-1-0 Recommends: libappindicator3-1 Section: default Priority: optional Homepage: https://sample.com Description: A sample description that starts with a single on first line. rules The rules file is a makefile that tells the Debian packaging tools how to build, install and clean up your package.\n*It\u0026rsquo;s a required part of the debian/ directory in a source package.\n#!/usr/bin/make -f %: dh $@ #!/usr/bin/make -f tells the system to use make to read the file. % is a pattern rule that matches any target. dh $@ calls the dh tool with the target name. (build, install, clean..) #!/usr/bin/make -f build: ./configure make install: mkdir -p $(DESTDIR)/usr/bin cp mybinary $(DESTDIR)/usr/bin/ clean: rm -rf build/ binary: dh_testdir dh_testroot dh_install dh_clean build: As the name suggests, this target is responsible for building the software. In this case, it compiles the software. install: Copies files to the staging area ($DESTDIR); set by the packaging tools. clean: Cleans up the build artifacts. binary: Runs debhelper commands to finalize the package. If you need to customize, you can override specific steps:\nrules #!/usr/bin/make -f override_dh_auto_build: gcc -o hello hello.c %: dh $@ copyright It\u0026rsquo;s a required file in every Debian package. It documents the copyright holders and licensing terms for the software and any files in contains. This file ensures users and redistributors know their legal righs and obligations regarding the package.\nFormat: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: mypackage Source: https://github.com/aperson/myproject Files: * Copyright: 2025 Yashwanth Rathakrishnan \u0026lt;yashwanth@example.com\u0026gt; License: GPL-3+ License: GPL-3+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. . On Debian systems, the complete text of the GNU General Public License version 3 can be found in \u0026#34;/usr/share/common-licenses/GPL-3\u0026#34;. \u0026lt;pkgName\u0026gt;-\u0026lt;version\u0026gt;-docs.docs This file lists the documentation files to be installed into the package\u0026rsquo;s documentation directory. Usually , it\u0026rsquo;s /usr/share/doc/\u0026lt;package-name\u0026gt;/.\nUsage examples:\nREADME CHANGELOG docs/usr-guide.txt README.Debian This file provides information specific to the Debian packaging of the software. It\u0026rsquo;s meant for the end-users and maintainers to understand Debian-specific changes, configurations or issues.\nREADME.source Describes the source package layout, any special source modifications, or non-standard packaging practices. Common Contents:\nHow the source package is structured. Any patches applied to the upstream source. How to regenerate files or apply patches. source/ This directory contains metadata about the source package format and options. Mostly, it contains a file named format, which specified the source package format.\n3.0 (quilt) upstream/ This directory is used to store information and metadata about the upstream source. Mostly, it contains files named metadata and changelog.\n","permalink":"https://docs.ayshell.dev/posts/packaging/file-structure-debian/","summary":"Detailed explanation of Debian packaging file structure.","title":"Packaging: Debian File Deep Dive"},{"content":"RPM Spec File: Complete Syntax \u0026amp; Options Guide An RPM .spec file is a recipe for building, installing and packaging software. It\u0026rsquo;s divided into sections, each with specific purposes.\nHeader Tags (metadata) Tag Purpose Example Name Name of the package Name: hello Version Upstream version Version: 1.0 Release Package release (increment on changes) Release: 1%{?dist} Summary Short description Summary: Simple hello world program License License type License: MIT URL Project website URL: https://example.com Source0 Main source file (tarball, etc) Source0: hello-1.0.tar.gz Patch0 Patch file Patch0: fix-type.patch BuildRequires Build-time dependencies BuildRequires: glibc Requires Runtime dependencies Requires: glibc Group Pacakge group (legacy; rarely needed) Group: Development/Tools Provides Virtual provides Provides: hello-binary Obsoletes Old pacakge gets replaces with the current Obsoletes: old-hello Conflicts Raises conflicts and can\u0026rsquo;t be installed Conflicts: hello-beta %description Section A longer, multi-line description of your package.\n%description A simple hello world program writter in C programming language for demonstration purposes. %prep Section Prepare sources, unpack files, apply patches, etc.\nCommon Macros:\n%setup - Unpacks source tarball -q = quite mode; less output -n \u0026lt;dirLocation\u0026gt; = unpacks source into custom directory -c = Create directory before unpacking -a \u0026lt;number\u0026gt; = Unpack additional sources (Source0, etc.) %patch - Apply patches Example:\n%prep %setup -q %patch0 -p1 %build Section Build/Compile the software.\nCommon Macros:\n%{optflags} = Compiler optimization flags; distro-recommended flags. %configure = Runs ./configure with standard options. %make_build = Runs make with parallel jobs. Example:\n%build %make_install %install Section Install files into a temporary buildroot.\nCommon Macros:\n%{buildroot} = Path to the temporary install root. %make_install = Runs make install DESTDIR=%{buildroot} Example:\n%install %make_install # or the manual installation would look like, %install mkdir -p %{buildroot}/usr/bin install -m 0755 hello %{buildroot}/usr/bin/hello %check Section Runs the tests to verify the build is successfull or not.\n%check make test #if that\u0026#39;s a binary file to test, we do something like ./hello | grep \u0026#34;Hello\u0026#34; %clean Section (Legacy) %clean rm -rf %{buildroot} Modern RPM tools clean up automatically, so this is mostly obsolete.\n%files Section List all files to include in the pacakge. Options \u0026amp; Macros:\n%doc \u0026lt;file\u0026gt;= Marks documentation files. %license \u0026lt;file\u0026gt; = Marks license files. %config \u0026lt;file\u0026gt; = Marks config files (preserved on upgrade). %attr(mode, user, group) \u0026lt;file\u0026gt; = Set permissions/ownership. %dir \u0026lt;dir\u0026gt; = Include a directory (not contents). %ghost \u0026lt;file\u0026gt; = File created at runtime, not in pacakge. Example:\n%files %doc README.md %licese LICENSE %config{noreplace} /etc/hello.conf /usr/bin/hello %attr(0755,root,root) /usr/bin/hello %changelog Section Document package changes.\n* DATE NAME \u0026lt;email\u0026gt; - VERSION-RELEASE - Change description Example:\n%changelog * Sat Jul 05 2025 Yashwanth Rathakrishnan \u0026lt;iamyaash@example.com\u0026gt; - 1.0-1 - Initial package Scriptlets Executes shell code at specific points\nScriptlet When it runs %pre Before install %post After install %preun Before uninstall %postun After uninstall %trigger --\u0026lt;pkgName\u0026gt; On package upgrade Example using %post:\n%post echo \u0026#34;Installation complete!\u0026#34; Special Macros \u0026amp; Usage %{name}, %{version}, %{release}: Expand to package name, version, release %{_bindir}, %{_libdir}, %{_datadir}: Standard directories (/usr/bin, /usr/lib, /usr/share) %{_sysconfdir}: /etc %{_mandir}: /usr/share/man %{_docdir}: /usr/share/doc %{?_smp_mflags}: Parallel make flags (e.g., -j4) .spec File Structure Name: hello Version: 1.0 Release: 1%{?dist} Summary: Simple Hello World program License: MIT URL: https://example.com Source0: hello-1.0.tar.gz BuildRequires: gcc %description A simple Hello World program written in C. %prep %setup -q %build gcc %{optflags} -o hello hello.c %install mkdir -p %{buildroot}/usr/bin install -m 0755 hello %{buildroot}/usr/bin/hello %check ./hello | grep \u0026#34;Hello\u0026#34; %files %doc README.md %license LICENSE /usr/bin/hello %post echo \u0026#34;Thank you for installing hello!\u0026#34; %changelog * Sat Jul 05 2025 Yashwanth Rathakrishnan \u0026lt;you@example.com\u0026gt; - 1.0-1 - Initial package Tips Macros make your spec file portable and maintainable. Always use %{buildroot} in %install to avoid polluting the real system. Use %doc, %license, and %config to properly classify files. Scriptlets should be used sparingly and only when necessary. Test your RPM with rpmbuild -ba \u0026lt;specfile\u0026gt; and install with rpm -i \u0026lt;rpmfile\u0026gt;. ","permalink":"https://docs.ayshell.dev/posts/packaging/file-structure-rpm-spec/","summary":"Detailed explanation of RPM package file structure.","title":"Packaging: RPM Spec File Deep Dive"},{"content":"What is tar? tar is primarily used for combining multiple files and directories into a single archive file (aka tarball), simplifying storage, backup, and transfer. It can also compress these archives to save disk space.\nSyntax\ntar \u0026lt;operation\u0026gt; [options] \u0026lt;archive-files\u0026gt; \u0026lt;files/directories\u0026gt; operation: The main action (eg:create,extract,list). options: Additional behaviours (eg: compression,verbosity). archive-files: Name of the archive. files/directories: What to include or extract. Essential tar Options Option Purpose -c Create a new archive -x Extract files from an archive -t List contents of an archive -f Specify archive file name -v Verbose output -z Use gzip compression -j Use bzip2 compression -J Use xz compression Practical Usage Create a basic tar archive: tar -cvf archive.tar file1.txt file2.txt directory1/ Combine file1.txt, file2.txt and directory1/ into a single archive named archive.tar.\nExtract an archive: tar -xvf archive.rar List contents of an archive: tar -tvf archive.tar Displays the contents of the archive without extracting.\nIntermediate tar Usage Compression Create a gzip-compressed archive: tar -czvf archive.tar.gz dirName/ Create a bzip2 compressed archive: tar -cjvf archive.tar.bz2 dirName/ Extracting With Compression Extract a gzip-compressed archive: tar -xzvf archive.tar.gz Extract a bzip2-compressed archive: tar -xjvf archive.tar.bz2 Extract to a specific directory: tar -xvf archive.tar /home/iamyaash/extractLocation/ Exclude files when archiving: tar -cvf archive.tar dirName/ --exclude=\u0026#34;*log\u0026#34; Excludes only .log files when archiving. 5. Extract a single file:\ntar -xvf archive.tar /archiveDir/file.txt If you want to extract only wordpress/xmlrpc.php from archive.tar, you would run the above command. This command will extract only that file, not the entire archive in the current directory.\nExtract a single file to a specific directory using the -C option: tar -xf archive.tar -C /target/directory path/to/file Extract files matching a pattern: tar -xvf archive.tar --wildcards \u0026#34;*.php\u0026#34; Advanced tar Usage Append or Update Files In An Archive Append a file: tar -rvf archive.tar newFile.txt Update only newer files: tar -uvf archive.tar updatedFile.txt Delete Files From An Archive tat --delete -f archive.tar unwantedFile.txt Check Archive Size tar -czf - dirName/ | wc -c Outputs the size in Bytes.\nVerify Archive Integrity tar -tvg archive.tar It lists the contents and checks for errors during listing.\nCompare Archive With File System tar -df archive.tar dirName/ Shows differences between the archive and current files.\nxz Compression: tar -cJvf archive.tar dirName/ Split Large Archives While tar itself doesn\u0026rsquo;t split files, you can combine it with split command:\ntar -cvf - dirName/ | split -b 100M -archive_part_ splits the archive into 100MB parts.\nThis is really a useful method of using archives, when you archive a single sometimes it get\u0026rsquo;s way over the size limit to copy to another machine. If a single file exceeds the certain size limit, the operating system won\u0026rsquo;t let you make the copy/move operation. It happens in Windows as far as I know. I have once tried to copy a games which is archived into a single file, when attempted to make copy operation, the Windows shows a dialog box stating that this file exceed the size limit and the operation can\u0026rsquo;t be made.\nTask Command Example Create archive tar -cvf archive.tar dir1/ Create gzip archive tar -czvf archive.tar.gz dir1/ Create bzip2 archive tar -cjvf archive.tar.bz2 dir1/ Extract archive tar -xvf archive.tar Extract gzip archive tar -xzvf archive.tar.gz Extract bzip2 archive tar -xjvf archive.tar.bz2 List archive contents tar -tvf archive.tar Exclude files tar -cvf archive.tar dir1/ --exclude='*.log' Append files tar -rvf archive.tar file.txt Delete from archive tar --delete -f archive.tar file.txt Extract to directory tar -xvf archive.tar -C /target/dir/ ","permalink":"https://docs.ayshell.dev/posts/linux/tools/tar-guide/","summary":"The tar command (short for tape archive) is a foundational tool in Linux for archiving and compressing files and directories","title":"Linux Tools: Getting Started with the tar Command"},{"content":"cat - Concatenate And Display File Contents The cat command is used to print the content of one or more files to the standard output(terminal). It can also be used to combine multiple files into one.\nEssential Options Options Description cat file.txt Display the contents of a file. cat file1.txt file2.txt Display contents of multiple files in order cat file1.txt file2.txt \u0026gt; both.txt Combine both files into a new file cat -n file.txt Number all output lines cat -b file.txt Number non-blank lines only cat -s file.txt Squeeze multiple blank lines cat -E file.txt Show $ at end each line Example Use this sample file: notes.txt\nLine 1: This is the first line. Line 2: This line has trailing spaces. Line 3: This line is followed by multiple blank lines. Line 4: The end of the sample file. Number all lines in notes.txt cat -n notes.txt Number only the non-blank notes.txt file cat -b notes.txt You have a file notes.txt with many consecutive blank lines. Display it with all multiple blank lines reduced to a single blank line. cat -s notes.txt How do you know where the lines ends? cat -E notes.txt head | tail - Show The First/Last Lines Of A File The head command displays the first N lines of a file (default is 10). The tail command displays the last N lines of a file (default is 10).\nExample head file.txt # first 10 lines head -n 8 file.txt # first 8 lines head -n 2 file.txt # Only the first 2 lines tails file.txt # last 10 lines tails -n 8 file.txt # last 8 lines tails -n 2 file.txt # Only the last 2 lines Note: tail -f, this flag is used to show the text files\u0026rsquo;s live update. Meaning, it follows the files as it grows. AKA, that\u0026rsquo;s how logging work, you see the last update (recently happened ones).\nless - Interactive Pager For Viewing Large Files the less command allows you to view and scroll through large files interactively, making it easier to navigate logs, reports, or any lengthy text files withtout loading the entire file into memory.\nEssential Options Key Description /pattern Search forward for pattern n/N Goto next/prev search match b Page up f Page down Examples View notes.txt and search for \u0026ldquo;yum\u0026rdquo; less notes.txt # Press -\u0026gt; /yum -\u0026gt; Enter Button How to page up and down while inside the less view b = Page Up f = Page Down How to go to next/prev search matches n = Next N = Previous ","permalink":"https://docs.ayshell.dev/posts/linux/tools/cat-head-tail-less/","summary":"Read and preview file contents using commands like cat, head, tail, less.","title":"Linux Tools: Basic File Viewing \u0026 Handling"},{"content":"cut - Extract Section From Each Line The cut command is used to extract specific fields or character positions from each line of input. It is especially useful for processing text files, logs, or command output where you need to isolate columns or substrings.\nEssential Options Option Description -d \u0026lt;delimiter\u0026gt; Specify the delimiter (default TAB) -f \u0026lt;list\u0026gt; Select fields (columns), separated by delimiter -c \u0026lt;list\u0026gt; Select character positions --complement Show everything except the selected field/char -s Suppress lines without the delimiter --output-delimiter \u0026lt;string\u0026gt; Use a custom output delimiter (GNU cut) Examples Use this sample file: employee.txt\nID,Name,Department,Salary,Location 1,Alice,Engineering,85000,New York 2,Bob,Sales,65000,San Francisco 3,Charlie,HR,60000,Chicago 4,David,Engineering,90000,Boston 5,Eva,Marketing,70000,Seattle Extracting fields by delimiter cut -d\u0026#39;,\u0026#39; -f2 emp.txt Extract name and salary cut -d\u0026#39;,\u0026#39; -f2,4 emp.txt Extract the first 3 characters of each line cut -c1-3 emp.txt Skip the header and extract \u0026ldquo;Deparment\u0026rdquo; and \u0026ldquo;Location\u0026rdquo; cat emp.txt | cut -d\u0026#39;,\u0026#39; -f3,5 Replace output delimiter with : instead of , cut -d\u0026#39;,\u0026#39; -f1,2 --output-delimiter=\u0026#39;:\u0026#39; emp.txt Display everything except the ID cut -d \u0026#39;,\u0026#39; -f1 --complement emp.txt sort - Sort Lines Of Text Files The sort command arranges lines in text files in alphabetical, numerical or custom column-based order. It\u0026rsquo;s a powerful tool for organizing data, finding duplicates, and preparing files for further processing.\nEssential Options Option Description sort -n Numeric Sort sort -r Reverse (descending) Sort sort -k Specify Sort Key (field/column) sort -u Unique Lines (remove duplicates) sort -t Specify Delimiter For Fields (default:space) Examples Use this sample file: emp.csv\nOrderID,Customer,Amount,Date 1003,Alice,250,2025-07-01 1001,Bob,100,2025-06-29 1005,Charlie,300,2025-07-03 1002,Eva,150,2025-06-30 1004,David,100,2025-07-02 Sort by Amount (3rd Column) numerically sort -t \u0026#39;,\u0026#39; -k3,3 -n emp.csv We need to separate the fields in order to access the 3rd column,\nUse -t \u0026quot;,\u0026quot; to specifiy delimiter which separates the lines with ,(comma) as delimiter. Then we specify -k3,3 which selects the 3rd column (because the fields are separated) and finally, we can sort it numerically by using -n. Sort by Date (4th column) alphabetically sort -t \u0026#39;,\u0026#39; -k4,4 emp.csv #sort alphabetically by default Sort by Customer Name (2nd column) in reverse order sort -t \u0026#39;,\u0026#39; -k2,2 -r emp.csv Remove duplicate lines while sorting by amount sort -t \u0026#39;,\u0026#39; -k3,3 -u emp.csv Sort by OrderID (1st column) numerically sort -t \u0026#39;,\u0026#39; -k1,1 -n emp.csv uniq - Report Or Filter Repeated Lines The uniq command is used to remove duplicate adjacent lines from a file or output. It is most effective when used after sort, as only consecutive duplicate lines are filtered.\nEssential Options Option Description -c Prefix lines by the number of occurrences -d Only print duplicate lines -u Only print unique lines Examples Use this sample file: hosts.txt\nserver1.example.com server2.example.com server1.example.com server3.example.com server2.example.com server2.example.com server4.example.com server5.example.com server5.example.com server5.example.com Show unique hostnames sort hosts.txt | uniq Count occurrences of each hostname sort hosts.txt | uniq -c Show only hostnames that appear more than once sort hosts.txt | uniq -d Show only hostnames that appear exactly once sort hosts.txt | uniq -u tr - Translate or Delete Characters The tr command is used to translate (replace), squeeze, or delete characters from standard input. It\u0026rsquo;s great for quick, in-place text transformations.\nEssential Options Option/Pattern Description tr 'a' 'A' Replace all a with A tr 'a-z' 'A-Z' Convert lowercase into uppercase tr -d '0-9' Delete all the digits tr -s ' ' Squeeze repeated spaces into one tr -cd 'A-Za-z\\n' Delete all except letter and newlines Examples Convert all lowercase letters to uppercase letters echo \u0026#34;Hello Bro!\u0026#34; | tr \u0026#39;a-z\u0026#39; \u0026#39;A-Z\u0026#39; Delete all digits from input echo \u0026#34;abc123\u0026#34; | tr -d \u0026#39;0-9\u0026#39; Squeeze multiple spaces into single space echo \u0026#34;a b c\u0026#34; | tr -s \u0026#39; \u0026#39; Replace commas with tabs echo \u0026#34;a,b,c\u0026#34; | tr \u0026#39;,\u0026#39; \u0026#39;\\t\u0026#39; ","permalink":"https://docs.ayshell.dev/posts/linux/tools/cut-sort-uniq/","summary":"Focuses on shaping, refining, or deduplicating data using cut, sort, uniq commands.","title":"Linux Tools: Data Extraction \u0026 Manipulation"},{"content":"Step 1: Prepare a Simple Program Create hello.c:\n// hello.c #include \u0026lt;stdio.h\u0026gt; int main() { printf(\u0026#34;Hello, RPM World!\\n\u0026#34;); return 0; } Compile it:\ngcc -o hello hello.c This generates an executable named hello.\nStep 2: Install Packaging Tools On Debian based distributions:\nsudo apt update -y \u0026amp;\u0026amp; sudo apt upgrade -y sudo apt install build-essential devscripts dh-make Explanation:\nbuild-essential: Include gcc and make. devscripts: Provides helpful tools like debuild. dh-make: Initializes Debian packaging files. Step 3: Prepare Source Directory Create a folder \u0026lt;package-name\u0026gt;-\u0026lt;version\u0026gt; and move the source code into it:\nmkdir hello-1.0/ mv hello.c hello-1.0 \u0026amp;\u0026amp; cd hello-1.0/ Ensure that you follow the naming conventions of the directory.\nStep 4: Initialize Debian Package Directory Run this command to create Debian packaging directory within the hello-1.0/:\ndh_make --createorig -s -y -p hello-1.0 Explanation:\n--createorig: Creates original tarball(.orig.tar.gz) in directory above the current directory. -s: Single binary package. -y: Assume \u0026ldquo;yes\u0026rdquo; for prompts. -p hello_1.0: Package name and version/ This create\nStep 5: Modify debian/ Files A debian/ folder is created when executing dh_make command:\ncd debian rm *.ex #.ex are example files and can be removed Edit control file\nnano control Source: hello-1.0 Section: utils Priority: optional Maintainer: Yashwanth Rathakrishnan \u0026lt;iamyaash@unknown\u0026gt; Rules-Requires-Root: no Build-Depends: debhelper-compat (= 13), gcc Standards-Version: 4.6.2 #Vcs-Browser: https://salsa.debian.org/debian/hello-1.0 #Vcs-Git: https://salsa.debian.org/debian/hello-1.0.git Package: hello-1.0 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, Description: Simple Hello World Program in C A simple beginner program that display \u0026#34;Hello World\u0026#34; text. Edit rules\n#!/usr/bin/make -f %: dh $@ chmod +x rules Create debian/install file and add:\nnvim debian/install hello /usr/bin #copies hello to /usr/bin directory Step 6: Build the Package Go back to one directory from debian/ (one level above debian/)\u0026quot;\ncd .. debuild -us -uc Step 7: Install and Test The packages are built and stored one level above the */debian/:\niamyaash@pi5:~/testBuild/hello-1.0 $ ll total 8.0K drwxr-xr-x 6 iamyaash iamyaash 4.0K Jul 4 14:13 debian -rw-r--r-- 1 iamyaash iamyaash 91 Jul 4 12:04 hello.c iamyaash@pi5:~/testBuild/hello-1.0 $ ll .. total 36K drwxr-xr-x 3 iamyaash iamyaash 4.0K Jul 4 12:13 hello-1.0 -rw-r--r-- 1 iamyaash iamyaash 3.1K Jul 4 14:13 hello-1.0_1.0-1_arm64.build -rw-r--r-- 1 iamyaash iamyaash 5.2K Jul 4 14:13 hello-1.0_1.0-1_arm64.buildinfo -rw-r--r-- 1 iamyaash iamyaash 1.8K Jul 4 14:13 hello-1.0_1.0-1_arm64.changes -rw-r--r-- 1 iamyaash iamyaash 2.3K Jul 4 14:13 hello-1.0_1.0-1_arm64.deb -rw-r--r-- 1 iamyaash iamyaash 2.4K Jul 4 14:13 hello-1.0_1.0-1.debian.tar.xz -rw-r--r-- 1 iamyaash iamyaash 786 Jul 4 14:13 hello-1.0_1.0-1.dsc -rw-r--r-- 1 iamyaash iamyaash 292 Jul 4 12:13 hello-1.0_1.0.orig.tar.xz Install the .deb package:\nsudo dpkg -i hello-1.0_1.0-1_arm64.deb Run:\nhello Remove/Uninstall:\ndpkg -r hello-1.0 Directory Structure (For Reference) iamyaash@pi5:~/testBuild $ ll -R . .: total 40K drwxr-xr-x 3 iamyaash iamyaash 4.0K Jul 4 14:30 hello-1.0 -rw-r--r-- 1 iamyaash iamyaash 3.4K Jul 4 14:32 hello-1.0_1.0-1_arm64.build -rw-r--r-- 1 iamyaash iamyaash 5.5K Jul 4 14:32 hello-1.0_1.0-1_arm64.buildinfo -rw-r--r-- 1 iamyaash iamyaash 2.0K Jul 4 14:32 hello-1.0_1.0-1_arm64.changes -rw-r--r-- 1 iamyaash iamyaash 3.9K Jul 4 14:32 hello-1.0_1.0-1_arm64.deb -rw-r--r-- 1 iamyaash iamyaash 2.5K Jul 4 14:32 hello-1.0_1.0-1.debian.tar.xz -rw-r--r-- 1 iamyaash iamyaash 789 Jul 4 14:32 hello-1.0_1.0-1.dsc -rw-r--r-- 1 iamyaash iamyaash 2.4K Jul 4 14:30 hello-1.0_1.0.orig.tar.xz -rw-r--r-- 1 iamyaash iamyaash 2.3K Jul 4 14:32 hello-1.0-dbgsym_1.0-1_arm64.deb ./hello-1.0: total 24K drwxr-xr-x 6 iamyaash iamyaash 4.0K Jul 4 14:32 debian -rwxr-xr-x 1 iamyaash iamyaash 69K Jul 4 14:28 hello -rw-r--r-- 1 iamyaash iamyaash 91 Jul 4 12:04 hello.c ./hello-1.0/debian: total 56K -rw-r--r-- 1 iamyaash iamyaash 186 Jul 4 14:30 changelog -rw-r--r-- 1 iamyaash iamyaash 503 Jul 4 14:31 control -rw-r--r-- 1 iamyaash iamyaash 1.9K Jul 4 14:30 copyright -rw-r--r-- 1 iamyaash iamyaash 10 Jul 4 14:32 debhelper-build-stamp -rw-r--r-- 1 iamyaash iamyaash 150 Jul 4 14:32 files drwxr-xr-x 4 iamyaash iamyaash 4.0K Jul 4 14:32 hello-1.0 -rw-r--r-- 1 iamyaash iamyaash 28 Jul 4 14:30 hello-1.0-docs.docs -rw-r--r-- 1 iamyaash iamyaash 63 Jul 4 14:32 hello-1.0.substvars -rw-r--r-- 1 iamyaash iamyaash 15 Jul 4 14:32 install -rw-r--r-- 1 iamyaash iamyaash 176 Jul 4 14:30 README.Debian -rw-r--r-- 1 iamyaash iamyaash 261 Jul 4 14:30 README.source -rwxr-xr-x 1 iamyaash iamyaash 690 Jul 4 14:30 rules drwxr-xr-x 2 iamyaash iamyaash 4.0K Jul 4 14:30 source drwxr-xr-x 2 iamyaash iamyaash 4.0K Jul 4 14:30 upstream Extract Contents Of Debian Pacakge I think the only way to easily extract the debian package is by using ar. You can use mc in case you want to take a look inside the package.\nar x packageName.deb ar is pre-installed in Debian based distro, and it will extract the contents in current directory.\n","permalink":"https://docs.ayshell.dev/posts/packaging/build-deb/","summary":"Create a simple \u0026ldquo;Hello World\u0026rdquo; C program, prepare necessary Debian packaging files (debian/) build the .deb pacakge, install it to test and remvoe it.","title":"Packaging: Build Your First Debian Package!"},{"content":"Step 1: Prepare a Simple Program Create hello.c:\n// hello.c #include \u0026lt;stdio.h\u0026gt; int main() { printf(\u0026#34;Hello, RPM World!\\n\u0026#34;); return 0; } Compile it:\ngcc -o hello hello.c This generates an executable named hello.\nStep 2: Install RPM Build Tools On Fedora (or any RPM-based system):\nsudo dnf install rpm-build rpmdevtools gcc Explanation:\nrpm-build: Main tool to build RPMs. rpmdevtools: Provides helper scripts (like rpmdev-setuptree). gcc: C compiler. Set up your RPM build environment:\nrpmdev-setuptree This creates a directory structure in your home directory:\n~/rpmbuild/ ├── BUILD ├── RPMS ├── SOURCES ├── SPECS ├── SRPMS Explanation:\nSOURCES: Where you put your source tarballs. SPECS: Where you keep spec files. RPMS: Built RPM packages go here. Step 3: Prepare the Source Tarball Move your hello.c file into a folder named hello-1.0/:\nmkdir hello-1.0 mv hello.c hello-1.0/ Create a tarball from that folder:\ntar czvf hello-1.0.tar.gz hello-1.0 Move it to SOURCES:\nmv hello-1.0.tar.gz ~/rpmbuild/SOURCES/ Explanation: RPM expects your source code to be in a tarball named \u0026lt;name\u0026gt;-\u0026lt;version\u0026gt;.tar.gz, containing a directory with the same name. This matches what %setup in the spec file expects.\nStep 4: Create the Spec File Create a .spec file, add the following:\ntouch ~/rpmbuild/SPECS/hello.spec Name: hello Version: 1.0 Release: 1%{?dist} Summary: Simple Hello World program License: MIT URL: http://example.com/ Source0: hello-1.0.tar.gz BuildRequires: gcc %description A simple Hello World program packaged as an RPM example. %prep %setup -q %build gcc %{optflags} -o hello hello.c %install mkdir -p %{buildroot}/usr/bin install -m 0755 hello %{buildroot}/usr/bin/hello %files /usr/bin/hello %changelog * Tue Jul 01 2025 Yashwanth Rathakrishnan \u0026lt;you@example.com\u0026gt; - 1.0-1 - Initial package Explanation (important!):\n%prep: Prepares the source (unpacks tarball). %build: Compiles the program. %install: Copies files to a temporary install location (%{buildroot}), simulating how they will be installed. %files: Lists which files get included in the final RPM. %changelog: Package history. Step 5: Build the RPM cd ~/rpmbuild/SPECS rpmbuild -ba hello.spec Explanation:\n-ba: Build both binary and source RPM. The resulting RPM will be inside:\n~/rpmbuild/RPMS/\u0026lt;architecture\u0026gt;/ What is RPM? RPM is a typical package that makes the package installation, upgrade and removal easier by handling dependencies automatically and ensuring files are placed in the correct locations. It contains, compiled software(binaries), metadata, configuration files, scripts and so on. It contains all the files that an RPM package should have.\nWhat is Source RPM? A Source RPM is often called SRPM, is a special type of RPM pcakge, that contains the _original source code(tarball), the spec file(build instructions), any patches or additional files needed for building the package.\nStep 6: Install, Test, and Remove Install the .rpm:\nsudo rpm -ivh ~/rpmbuild/RPMS/x86_64/hello-1.0-1.fc42.x86_64.rpm -i = install; Tell rpm to install a new package. -v = verbose; Shows detailed output while installing, so you can see what\u0026rsquo;s happening. -h = Prints a progress bar with # symbols as the package installs. Test:\nhello Output should be:\nHello, RPM World! Uninstall it:\nsudo rpm -e hello Check:\nhello # bash: /usr/bin/hello: No such file or directory Write program ➜ Package sources ➜ Write .spec ➜ Build ➜ Install ➜ Test ➜ Remove\nExtract Content Of An RPM Package Method 1: Use rpm2cpio + cpio\nrpm2cpio packageName | cpio -idmv rpm2cpio packageName: converts RPM to a cpio archive stream. cpio -idmv: extract files i: extract d: create directories as needed m: preserve modification times v: verbose output Method 2: Use mc (Midnight Commander)\nsudo dnf install mc #it doesn\u0026#39;t come pre-built in any distro mc #execute this, navigate to the rpm file ","permalink":"https://docs.ayshell.dev/posts/packaging/build-rpm/","summary":"Create a simple \u0026ldquo;Hello World\u0026rdquo; C program, write a .spec file, build an RPM package with rpmbuild, install it to test, and then remove it.","title":"Packaging: Build Your First RPM Package!"},{"content":"Philosophies and Design Goals RPM - Red Hat Package Manager Originally developed by Red Hat, now widely being used in Fedora, CentOS, RHEL, openSUSE, etc.\nPhilosophy Strong focus on scalability, larger enterprise environments, and fine-grained control over packaging and system policies.\nThe core design goals and philosophy of RPM include:\nEase of Maintainance (Independent Pacakge Operations): RPM enables independent install/remove/upgrade of packages, simplifying the system maintainance.\nUpgradability(Upgrade without restart): RPM allows upgrading in-place without having a full system restart. It also preserves the user configuration, while updating.\nScalablity(Enterprise-Friendly features): RPM is more enterprise-friendly with it\u0026rsquo;s robust features, such as fine-grained package management, system verification and upgradability.\nPowerful Querying(Database usage for package information): RPM stores information about the installed packages within a dedicated database on your machine, specifically /var/lib/rpm/ directory. The database contains metadata about each installed packages, such as name, version, config, description, and so on. It helps easy querying to get information from database rather than scanning the actual files.\nPristine Sources(Separated instructions for easier maintainanace): Maintains the changes and build instructions separated, for easier maintainance and higher software quality of upstream sources.\nSystem Verification(Verify Package Authenticity \u0026amp; Integrity): RPM can verify package integrity using the checksum or GPG keys, notifying the user of inconsistencies and preserving modified configuration files during reinstallation.\nFine-Grained Control(Detailed control over package): It provides detailed control over packaging, installation, and system policies, which is essential for enterprises and multi-user environment.\nDefining Build Instructions A single .spec file is at the heart of every RPM pacakge. It serves as the blueprint for building, installing and packaging software.\nCentralized Instructions The .spec file contains all the metadata, scripts, and build instructions required to create an RPM package. Such as:\nPackage name, version, description, summary, and release. License and upstream source information. Build dependencies and runtime dependencies. Detailed build and install scripts(using shell commands). File lists specifying which files go into the package. Pre- and post-install scripts (for setup or cleanup tasks). Human-Readable and Editable The .spec file is a plain text file, making it easy for packagers to review and modify. Example\nName: example Version: 1.0 Release: 1%{?dist} Summary: Summary of the example package License: MIT Source0: https://example.com/example-1.0.tar.gz BuildRequires: gcc, make, Required: python3, openssl %description This is an example RPM pacakge. %prep %setup -q %build make %{?_smp_mflags} %install make install DESTDIR=%{buildroot} %files /usr/bin/example %changelog * Thu Jul 03 2025 John Doe \u0026lt;jdoe@example.com\u0026gt; - 1.0-1 - Initial package In simple terms, one .spec file is used to define build instructions. It contains all metadata, scripts, build instruction in one place.\nDependency Declaration Style RPM uses a declaration approach for handling dependencies, all specified directly within .spec file. Explicitly lists Requires, BuildRequires, Conflicts, etc., inside .spec file.\nKey Tags\nRequires: Lists pacakges that must be present for the RPM to work on at runtime. BuildRequires: Lists pacakges needed only during the build process, not at runtime. Conflicts: Specifies packages that cannot be installed at the same time as this pacakge. Obsoleted: Indicates that this package replaces another package. Provides: This package gives you the features (not just a file). In simple terms, it does the job and other packages depends on it. Package Scripts RPM packages include special scripts that run at certain points during installation or removal. All these scripts are written inside .spec file.\n%pre echo \u0026#34;It runs before the package is installed\u0026#34; echo \u0026#34;Preparing to install...\u0026#34; %post echo \u0026#34;It runs after the packaage is installed\u0026#34; echo \u0026#34;Installation complete!\u0026#34; %preun echo \u0026#34;Preparing to remove...\u0026#34; echo \u0026#34;Runs before the pacakge is uninstalled\u0026#34; %postun echo \u0026#34;Removal complete!\u0026#34; echo \u0026#34;Runs after the pacakge is uninstalled\u0026#34; Packaging Tools The main tool used to build RPM packages from .spec files and source code is rpmbuild.\nrpmbuild -qa myPacakge.spec Installing And Querying Packages\nrpm The low-level tool for installing, querying, and managing RPM packages directly. Install Package rpm -ivh myPacakge.rpm Query Package rpm -q myPackage dnf The modern high-level package manager for RPM-based systems and handles dependencies automatically (there\u0026rsquo;s no need for manual dependency installation). Install/Remove Package sudo dnf install myPacakge #install sudo dnf remove myPackage #uninstall yum The older high-level package manager, similar to dnf but got replaced by dnf. Verification And Signatures GPG Signatures: RPM packages can be signed with GPG keys. This ensures the authenticity and integrity of the pacakge. Use this command to verify a package\u0026rsquo;s signature: rpm --checksig myPacakge.rpm Checksums: RPM uses checksums (such as SHA256) to ensure that files within the package have not been altered or corrupted.\nFile Verification: RPM allows yout to verify installed files against the package metadata.\nrpm -V myPackage Debian Package Designed for Debian distributions, now also used by Ubuntu and it\u0026rsquo;s derivatives.\nPhilosophy Emphasis on simplicity and community-driven maintainance; often aims to make packaging easier and more accessible for volunteers and smaller teams. Instead of a single spec files like RPM, it uses a debian/ directory with multiple small files to descrive package behaviour.\nSimplicity: Debian emphasizes simple, understandable packaging processes. The goal is to make it easy for anyone, including volunteers and small teams, to contribute. Community-Driven Maintenance: Most Debian packages are maintained by community volunteers, not by a single company. This encourages collaboration, transparency, and wide participation. Accessibility: The packaging system is designed so new contributors can easily learn and participate, lowering the barriers to entry. Defining Build Instructions The debian/ directory contains several small, purpose-specific files that together describs how the package is built, installed, and maintained.\ncontrol - list of package metadata and dependencies. rules - contains build instrucitons. changelog - list changes and copyright information for the pacakge. install - specifies which files should be insatlled and where. preinst, postinst, prerm, postrm - Scripts that run before/after or removal of the package. compat - Set the compatibility level for the package tool. (replace by debian/control in newer versions) source/format - Specifies the source package format. Example\ndebian/ ├── changelog ├── compat ├── control ├── copyright ├── install ├── postinst ├── prerm ├── rules ├── source/ │ └── format Dependency Declaration Style Dependencies for Debian packages are specified in the debian/control file.\nKey Fields\nDepends: List packages that must be installed for this package to work at runtime. Pre-Depends: List packages that must be installed and configured before this pacakge is unpacked. Conflicts: List packages that cannot be installed at the same time as this package. Recommends: Most users will want these installed for full functionality. Suggests: Useful, but not needed for normal operation. Breaks: Installing this package may break the listed packages, so the system will prevent them from being installed together. Enhances: It’s the opposite of Suggests: instead of saying “I suggest you install X,” it says “I enhance X.” Provides: Other packages can depend on ths provided feature, not just the package name. Example\nPackage: myapp Version: 1.0 Section: utils Priority: optional Architecture: amd64 Depends: libc6 (\u0026gt;= 2.29), python3 Pre-Depends: dpkg (\u0026gt;= 1.15.6~) Conflicts: oldapp Description: My example application A longer description of my example application. Package Scripts Debian uses separate script files in the debian/ directory for package lifecycle events.\ndebian/ ├── preinst #runs before the package is installed/udgraded ├── postinst #runs after the package is installed/udgraded ├── prerm #runs before the package is removed ├── postrm #runs after the package is removed Packaging Tools dpkg-buildpackage The core tool for building Debian packages. It processes the source directory(debian/) and creates .deb files. It can be run directly for manual control over the build process. debuild The higher level wrapper aroud dpkg-buildpackage and other tools. It automates running dpkg-buildpackage, checks packages with lintian, handles cryptographic signing, and manages build logs. Useful for simplifying and automating the build process, especially for uploads to Debian repositories. Installing And Managing Packages:\ndpkg The low-level tool for installing, removing, and querying .deb pacakges directly. dpkg -u myPackage.deb apt The high-level package manager for Debian-based systems. Handles dependency resolution, package downloads, and installations from repositories. apt install mypackage Verification and Signatures GPG Signatures: Debian package and repositories can be signed using GPG keys. This ensures the package or repository comes from a trusted source and hasn\u0026rsquo;t been tampered with.\nVerification of .deb Package To verify, we use tools like dpkg-sig and debsig-verify are used to sign and verify .deb package files.\nImport the public key first, then dpkg-sig --verify myPackage.deb debsig-verify myPackage.deb A successfull verification will show a message like GOODSIG. APT Resitory Verification Packages installed via apt are signed! Meaning, all the downloads from apt are trusted.\nChecksums\n.deb signature verification is disabled by default and must be enabled by editing /etc/dpkg/dpkg.cfg and setting up the necessary policy files.\n","permalink":"https://docs.ayshell.dev/posts/packaging/rpm-deb-pkg-diff/","summary":"Philosophies, design goals, and build process of \u0026ldquo;Red Hat Package Manager\u0026rdquo; and \u0026ldquo;Debian Package\u0026rdquo;.","title":"Packaging: Conceptual Differences Between RPM and DEB"},{"content":"Why Do We Need To Package Software At All? Easier Software Installation The simple answer is to make software installation easier. Because, without packages you\u0026rsquo;ve to download source code, figure out the dependencies manually, compile it yourself, copy files to the right places (like /usr/bin, /usr/share) and so on.\nThings get really complicated without a package. That\u0026rsquo;s why we put everything into one package which takes care of installing the software without requiring much manual work.\nIn simple terms, a package bundles all the above mentioned manual tasks and let\u0026rsquo;s you install the software with just one command.\nsudo dnf install appName #if it\u0026#39;s an RPM based distro sudo apt install appName #if it\u0026#39;s a DEB based distro Handling Dependencies Automatically A package contains information on what other dependencies and the exact version it requies to run the software properly.\nSince the package bundles this information, package managers(dnf,apt) can check and install the necessary dependencies automatically, so you don\u0026rsquo;t end up with a \u0026ldquo;works on my machine\u0026rdquo; scenario\nStandardize Software Across System Packaging follow strict guidelines, so all the package file structures are consistent and files go to standard locations. Making it easy for developers and maintainers to knowing where to look for thinig and for security teams to audit and patch easily.\nAll of this is possible because packages follows the certain standards and guidelines, which makes it easier for others to work on them.\nIt\u0026rsquo;s not necessarily the same across all packaging types. For example, we\u0026rsquo;ll focus on .rpm here, but rpm has its own guidelines, and deb has its own as well. Although the method of packaging is similar in principle, they are not exactly the same.\nEnabling Safer Updates and Removals Packaging allows you to update or remove softwares cleanly, without leaving junk beihind.\nA package includes a file list to install, along with uninstallation scripts (_ known as post/pre uninstall scripts_).\nIt also manages versioning and checksums to ensure files are properly tracked and verified.\nIt allows us to safely upgrade or completely remove software, keeping the system clean and consistent.\nSupport System Security And Integrity Packages can be signed using GPG keys, so you know they come from a trusted source and have not been tampered with.\nBasically, you can verify the package\u0026rsquo;s signature using the developer\u0026rsquo;s public key to ensure that it actually comes from the developer and has not been modified.\nImagine building a PC from scratch, you would have to gather individual parts and components. A package is like buying a pre-build PC, so you can just \u0026ldquo;plug and play\u0026rdquo;\nWhat Is Inside A Package RPM- Red Hat Package Manager 1. Payload (the actual files) This is what finally gets installed on your system:\nBinaries: /usr/bin/appName Libraries: /usr/lib/libappName.so Configuration Files: /etc/appName/config.conf Documentation: /etc/share/doc/appName 2. Metadata It includes information about the package itself:\nName (e.g: appName) Version (8.2.4) Release (packager\u0026rsquo;s iteration, eg: 1.fc40) Architecture arm, arm64, x86_64 Summary and detailed description License Maintainer Information 3. Dependency Information Lists what other packages are required for the software to run properly:\n#examples Requires: python3 \u0026gt;= 3.8 Conflicts: oldlib \u0026lt; 2.0 4. Scripts (Optional) Special scripts that run automatically when installing or removing the package:\nPre-install(preint) - runs before install Post-install(postint) - runs after install Pre-remove(prerm) - runs before removal Post-remove(postrm) - runs after removal For .rpm packages, these are usually defined as %pre. %post. %preun, and %postrun.\nExample uses:\nCreating system users or groups Creating directories and necessary files Seting up permissions Starting or enabling services 5. Checksums \u0026amp; Signatures Every file include a checksum to ensure it isn\u0026rsquo;t corrupted or have been tampered with. Packages can be signed using GPG keys, that helps verifying the authenticity and integrity of the package. 6. Changelog (Optional) Contains information about what changes have been made in each version of the package.\nIt helps track added features, changes, fixes, and other updates. This is useful for both users and maintainers to understand the package’s evolution and history.\nDebian Package Manager A .deb package is basically an ar archive (Unix archive format), which internally contains:\ndebian-binary control.tar.{gz|xz|zst} data.tar.{gz|xz|zst}r 1. debian-binary A plain text file, almost always contains the version of the pacakging format(describes the version of the packaging format, not the software itself):\n2.0 It mostly used by the tool to know how to unpack and handle the package.\n2. control.tar.gz (or .xz .zst) This archive contains all metadata and control script:\ncontrol file: Basic metada (name, version, architecture, dependencies) postinst, preinst, postrm, prerm: Pre/post install/remove scripts. conffiles: List configuration files that should be preserved on upgrades. md5sums: Checksums of installed files for integrity checks. 3. data.tar.gz (or .xz, zst) This archive contains the actual payload:\nAll binaries, libraries, documentations, configurations, because they are going to be ones that will appear in the final system after installation. Example Layout:\n/usr/bin/appName /usr/share/doc/appName/README /etc/appName/config.conf ","permalink":"https://docs.ayshell.dev/posts/packaging/introduction-to-packaging/","summary":"Provides an overview of what is a package and what is inside a package in Linux? Covers the essential and introduction part of packaging only.","title":"Packaging: Introduction to Packaging in Linux"},{"content":"sed - Stream Editor It read line by line and allows you to substitute, delete or transform text streams.\nsed [options] \u0026#39;command\u0026#39; file Essential Commands \u0026amp; Options Command Description s/pattern/replacement Substitute pattern with replacement (first match) s/pattern/replacement/g Substitute all matches in line d Delete line p Print line -n Suppress automatic printing -i Edit file in place Example sed \u0026#39;s/decline/accept\u0026#39; status.txt # replace \u0026#34;decline\u0026#34; with \u0026#34;accept\u0026#34; sed \u0026#39;s/decline/accept/g\u0026#39; status.txt # replace all \u0026#34;decline\u0026#34; with \u0026#34;accept\u0026#34; sed \u0026#39;/^#/d\u0026#39; code.py #deletes all the comments sed -n \u0026#39;/error/p` code.py\u0026#39; #print lines that only contains \u0026#39;error\u0026#39; Exercises In server.conf, replace all occurences of localhost with 127.0.0.1, and save changes in place. sed -i \u0026#39;s/localhost/127.0.0.1/g\u0026#39; server.conf #edits the file in place In logfile.txt, delete all lines that start with #. sed -i \u0026#39;/^#/d\u0026#39; logfile.txt In users.txt, print only lines that contain the word admin. sed -n \u0026#39;/admin/p\u0026#39; users.txt #-n suppresses default output In data.txt, add the string \u0026quot;END\u0026quot; to the end of every line. sed \u0026#39;s/$/\u0026#34;END\u0026#34;/\u0026#39; data.txt In report.txt, replace the first occurence of ERROR with WARNING in each line, but only print lines where substitution happened. sed -n \u0026#39;s/ERROR/WARNING/p\u0026#39; report.txt awk - Text And Field Processing awk processes text line by line and splits each into fields(columns). Great for reports, CSVs, logs.\nawk \u0026#39;pattern { action }\u0026#39; file Built-In Variables Variable Descriptio $0 Entire Line $1, $2\u0026hellip; First, second field, etc. NF Number of fields NR Line number Example awk \u0026#39;{print $1}\u0026#39; file.txt #print only the first line awk -F \u0026#39;:\u0026#39; \u0026#39;{print $1}\u0026#39; /etc/password #print usernames awk \u0026#39;$3 \u0026gt; 50\u0026#39; data.txt #print lines where third field \u0026gt; 50 awk \u0026#39;{sum += 2} END {print sum}\u0026#39; prices.csv #sum of 2nd field awk \u0026#39;/error/\u0026#39; log.txt #print lines containing \u0026#39;error\u0026#39; Exercises In report.csv(comma-separated), print only the first and third columns. awk -F, \u0026#39;{print $1 \u0026#34;,\u0026#34; $3}\u0026#39; report.csv In sales.txt(space-separated), print all lines where the second field (column) is greater than 500. awk \u0026#39;$2 \u0026gt; 500\u0026#39; sales.txt In scores.txt, calculate the average of values in the third column and print the result. awk \u0026#39;{sum += $3; count++} END {print sum/count}\u0026#39; scores.txt In /etc/passwd, print usernames (first field) and their default shells (last field) awk -F: \u0026#39;{print $1, $NF}\u0026#39; /etc/passwd In data.csv, print lines where the first field equals \u0026quot;FAILED\u0026quot; awk -F, \u0026#39;$1 == \u0026#34;\\\u0026#34;FAILED\\\u0026#34;\u0026#34;\u0026#39; data.csv ","permalink":"https://docs.ayshell.dev/posts/linux/tools/awk-sed/","summary":"Modify or reformat text streams or files; Command: awk \u0026amp; sed","title":"Linux Tools: Transform \u0026 Edit"},{"content":"grep - Global Regular Expression Print It basically searches for patterns in text(files or streams) using regular expressions.\ngrep [option] pattern [file..] Essential Options Option Description -i Ignore case -r/-R Recursive search in directories -n Show line number -v Invert match (Shows text that don\u0026rsquo;t match) -c Count matching lines -l List filenames with match -H Show filename with match (useful when grepping multiple files) --color=auto Highlight matches -E / -e Use extended regex (like egrep) -F Fixed string search (no regex + faster) Example grep \u0026#34;error\u0026#34; /var/log/syslog # shows text that matches \u0026#34;error\u0026#34; grep -i \u0026#34;warning\u0026#34; *.log # case insensitive grep -r \u0026#34;failed password\u0026#34; /var/log grep -v \u0026#34;^#\u0026#34; /etc/ssh/ssh_config #invert match, in this case it excludes the comments grep -c \u0026#34;404\u0026#34; access.log #show 404 line precisely Exercises Find all case-insensitive matches of the worf failed in /var/log/auth.log. grep -i failed /var/log/auth.log Search all .conf files in /etc for lines containing PermitRootLogin. grep -r PermitRootLogin /etc --include=\u0026#34;*.conf\u0026#34; List files under /var/log that contain the word kernel. grep -rl kernel /var/log Show all non-comment lines from /etc/fstab. grep -v \u0026#34;^#\u0026#34; /etc/fstab Count how many times the word sshd appears in /var/log/messages. grep -c sshd /var/log/messages find Locate Files Based On Attributes It basically searches for files and directories based on name, size, date, permissions, etc. In simple terms, it searches using metadata of the files and directories rather than just using the name of the file.\nfind [path] [expression] Essential Options Option Description -name \u0026quot;pattern\u0026quot; Match file/directory name (case-sensitive) -iname \u0026quot;pattern\u0026quot; Match file/directory name (case-insensitive) -wholename \u0026quot;pattern\u0026quot; Matches the whole file/directory name (case-insensitive) -type f/d File(f) or directory (d) -size [+/-]N[c/k/M/G] File size -mtime [+/-N] Modified exactly N days ago (+N older |-N newer) -newer file Modified after a specific date -perm Permissions (eg: 644/u+w) -user / -group Owned by user/group -exec CMD {} \\; Execute command on result -delete Delete matching files (not recommended for beginners) -maxdepth / -mindepth Limit directory traversal Example find / -name \u0026#34;iamyaash\u0026#34; find /etc -type f -iname \u0026#34;*.conf\u0026#34; find /home -type f -size +100M find /var/log -mtime -2 find /tmp -type f -user iamyaash find . -type f -name \u0026#34;*.log\u0026#34; -exec grep -H \u0026#34;error\u0026#34; {} \\; Exercises Find all .log files modified in the last 2 days in /var/log. find /var/log -type f -mtime -2 -name \u0026#34;*.log\u0026#34; Search for files larger than 10MB in your home directory find /home/iamyash -type f -size +10M Find all .ssh scripts and list their permissions find . -type f -name \u0026#34;*.ssh\u0026#34; -exec ls -l {} \\; Delete all .tmp files in /tmp older than 7 days find /tmp -type f -name \u0026#34;*.tmp\u0026#34; -mtime +7 -exec rm -rf {} \\; Combine find and grep to search for \u0026ldquo;database\u0026rdquo; in all .conf files under /etc. find /etc -type f -name \u0026#34;*.conf\u0026#34; -exec grep \u0026#34;database\u0026#34; {} \\; ","permalink":"https://docs.ayshell.dev/posts/linux/tools/grep-find/","summary":"Searches for patterns in text (files or streams) using regular expressions and Searches for files and directories based on name, size, date, permissions, etc.","title":"Linux Tools: Search \u0026 Filter"},{"content":"What is journalctl Filters? You can use filters with journalctl to narrow down and control which log entries are displayed. journalctl supports a wide range of filtering options, both by structured fields and by command-line flags.\nStructured Fields: SYSLOG_IDENTIFIER, _SYSTEMD_UNIT, _UID, etc Command-Line Fields: --since, --until, -u, -p, --grep, etc Common journalctl Filters Filter Type Example Command Description By Time journalctl --since \u0026quot;8 hours ago\u0026quot; Shows logs since a specific time By Service/Unit journalctl -u nginx.server Show logs for a specific server/unit By Priority journalctl -p warning Show logs at/above a certain severity By Field journalctl SYSLOG_IDENTIFIER=sudo Show logs where a field matches a value By Boot journalctl -b -1 Shows logs from the previous boot By Keyword journalctl --grep \u0026quot;error\u0026quot; Shows logs containing a keyword Advanced journalctl Filters Filter Type Example Command Description By User ID journalctl _UID=user_id Filter logs by the user ID of the process that generated them By Group ID journalctl _GID=group_id Filter logs by the group ID of the process that generated them By Process ID journalctl _PID=process_id Filter logs by process ID By Process name journalctl _COMM=nginx Filter by process name (eg. _COMM=nginx) By Hostname journalctl _HOSTNAME=hostname Filter logs by hostname By Executable Path journalctl _EXE=exe_path Filter logs by executable path (eg: /usr/local/bin/hugo) By Boot Session journalctl _BOOT_ID=boot_id Filter logs by a specific boot session By Audit Session journalctl _AUDIT_SESSION=session_id Filter logs by audit session ID By Syslog Facility Code journalctl _SYSLOG_FACILITY=facility_number Filter by syslog facility code Alternatively, you can find the available filters in journalctl by using:\njournalctl --fields Example View logs since yesterday Filter logs for a specific service Show only error messages Filter by time range Show logs from the previous boot Filter logs by user Search for a keyboard Limit the number of output lines ","permalink":"https://docs.ayshell.dev/posts/linux/journald/filters-journalctl/","summary":"\u003ch1 id=\"what-is-journalctl-filters\"\u003eWhat is \u003ccode\u003ejournalctl\u003c/code\u003e Filters?\u003c/h1\u003e\n\u003cp\u003eYou can use filters with \u003ccode\u003ejournalctl\u003c/code\u003e to narrow down and control which log entries are displayed. \u003ccode\u003ejournalctl\u003c/code\u003e supports a wide range of filtering options, both by structured fields and by command-line flags.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eStructured Fields: \u003ccode\u003eSYSLOG_IDENTIFIER\u003c/code\u003e, \u003ccode\u003e_SYSTEMD_UNIT\u003c/code\u003e, \u003ccode\u003e_UID\u003c/code\u003e, etc\u003c/li\u003e\n\u003cli\u003eCommand-Line Fields: \u003ccode\u003e--since\u003c/code\u003e, \u003ccode\u003e--until\u003c/code\u003e, \u003ccode\u003e-u\u003c/code\u003e, \u003ccode\u003e-p\u003c/code\u003e, \u003ccode\u003e--grep\u003c/code\u003e, etc\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"common-journalctl-filters\"\u003eCommon \u003ccode\u003ejournalctl\u003c/code\u003e Filters\u003c/h2\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eFilter Type\u003c/th\u003e\n          \u003cth\u003eExample Command\u003c/th\u003e\n          \u003cth\u003eDescription\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Time\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl --since \u0026quot;8 hours ago\u0026quot;\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eShows logs since a specific time\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Service/Unit\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl -u nginx.server\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eShow logs for a specific server/unit\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Priority\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl -p warning\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eShow logs at/above a certain severity\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Field\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl SYSLOG_IDENTIFIER=sudo\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eShow logs where a field matches a value\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Boot\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl -b -1\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eShows logs from the previous boot\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Keyword\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl --grep \u0026quot;error\u0026quot;\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eShows logs containing a keyword\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch3 id=\"advanced-journalctl-filters\"\u003eAdvanced \u003ccode\u003ejournalctl\u003c/code\u003e Filters\u003c/h3\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eFilter Type\u003c/th\u003e\n          \u003cth\u003eExample Command\u003c/th\u003e\n          \u003cth\u003eDescription\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy User ID\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _UID=user_id\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter logs by the user ID of the process that generated them\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Group ID\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _GID=group_id\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter logs by the group ID of the process that generated them\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Process ID\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _PID=process_id\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter logs by process ID\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Process name\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _COMM=nginx\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter by process name (eg. \u003ccode\u003e_COMM=nginx\u003c/code\u003e)\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Hostname\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _HOSTNAME=hostname\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter logs by hostname\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Executable Path\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _EXE=exe_path\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter logs by executable path (eg: \u003ccode\u003e/usr/local/bin/hugo\u003c/code\u003e)\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Boot Session\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _BOOT_ID=boot_id\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter logs by a specific boot session\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Audit Session\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _AUDIT_SESSION=session_id\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter logs by audit session ID\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eBy Syslog Facility Code\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ejournalctl _SYSLOG_FACILITY=facility_number\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eFilter  by syslog facility code\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e\u003cstrong\u003eAlternatively\u003c/strong\u003e, you can find the available filters in \u003ccode\u003ejournalctl\u003c/code\u003e by using:\u003c/p\u003e","title":"Linux: Advanced Filtering and Analyzing System Logs with journalctl"},{"content":"Checking Service Status In Detail The systemctl status command provides detailed information about a service, including it\u0026rsquo;s current state (active, inactive, failed), recent log entries, and reasons for failure if the service is not running.\nExample Command:\nsudo systemctl status apache2 #or httpd service sudo systemctl status httpd Output:\niamyaash@pi5:~ $ sudo systemctl status firewalld.service ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/lib/systemd/system/firewalld.service; enabled; preset: enabled) Active: active (running) since Sun 2025-06-29 20:30:48 IST; 1s ago Docs: man:firewalld(1) Main PID: 7956 (firewalld) Tasks: 2 (limit: 9585) CPU: 279ms CGroup: /system.slice/firewalld.service └─7956 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid Jun 29 20:30:48 pi5 systemd[1]: Starting firewalld.service - firewalld - dynamic firewall daemon... Jun 29 20:30:48 pi5 systemd[1]: Started firewalld.service - firewalld - dynamic firewall daemon. The output includes:\nLoaded: Whether the service is loaded and enabled/disabled. Active: Current status(active, inactive, failed). Main PID: The main process ID. Tasks, Memory, CPU: Resource usage (if available). Logs: Recent log entries for troubleshooting. Starting, Stopping, Restarting, And Reloading Services This is relatively simple, and it\u0026rsquo;s the bare minimum requirement to use systemctl to manage systemd daemon.\nWe can control the operation of a service using start, stop, restart, and reload.\nsudo systemctl start firewalld # start the service sudo systemctl stop firewalld # stop the service sudo systemctl restart firewalld # stop and start the service sudo systemctl reload firewalld # reload configuration without stopping Use reload for configuration changes that do not require a full restart.\nEnabling And Disabling Services At Boot The term enable and disable in systemd services indicates, that a service can start automatically at boot(enable), or to prevent automatic startup(disable).\nsudo systemctl enable firewalld # get started at boot sudo systemctl disable firewalld # won\u0026#39;t start at boot Masking And Unmasking Services Masking a service prevents it from being start, even manually. Unmasking removes this restriction.\nsudo systemctl mask firewalld # prevent all starts sudo systemctl unmask firewalld # allow starts again Masking creates a symbolic link in /etc/systemd/system that overrides the service file.\nUnderstanding And Working With systemd Targets systemd uses \u0026ldquo;targets\u0026rdquo; to group services and define the system state (eg: multi-user, graphical, rescue).\nPurpose:They act as synchronization points during boot, shutdown, and state changes, allowing systemd to manage dependencies and ensure services start in the correct order.\nFile Format: Target units ends with .target and are defined in /usr/lib/systemd/system or /etc/systemd/system.\nYou can switch between targets using systemctl isolate.\nCommon targets: multi-user.target: Text-based multi-user mode. graphical.target: Graphical user interface mode. rescue.target: Single-user rescue mode. poweroff.target: For shutting down or rebooting the system. For compatibility, systemd provides runlevel*.target units that map to traditional SysV runlevels.\nAdvanced Usage and Features Creating Custom Targets: You can define your own target files to group custom services or define new system states. Dependencies: Targets can depend on other targets or units using Wants=, Requires=, Before=, and After= directives in unit files. Multiple Active Targets: Unlike traditional runlevels, multiple targets can be active at the same time. Viewing Active Targets: Use systemctl list-units --type=target to see all active and loaded targets. Changing the Default Target: Use systemctl set-default \u0026lt;target\u0026gt; to change the default boot target. Isolating a Target: Use systemctl isolate \u0026lt;target\u0026gt; to switch to a different target at runtime (eg: from graphical to rescue mode) Nested Targets: Some targets inherit all services from another target and add more (eg:graphical.target includes all from multi-user.target plus a display manager). Essential Commands List all targets: systemctl list-unit --type=target Get current default target systemctl get-default Set default target sudo systemctl set-default multi-user.target Isolate a target (switch state) sudo systemctl isolate rescue.target View dependencies of a target systemctl show -p Wants --value multi-user.target systemctl show -p Requires --value multi-user.target You can easily create a custom target file by duplicating the existing target and edit dependencies as needed.\n","permalink":"https://docs.ayshell.dev/posts/linux/systemd/service-management/","summary":"\u003ch1 id=\"checking-service-status-in-detail\"\u003eChecking Service Status In Detail\u003c/h1\u003e\n\u003cp\u003eThe \u003ccode\u003esystemctl status\u003c/code\u003e command provides detailed information about a service, including it\u0026rsquo;s current state (\u003cem\u003eactive, inactive, failed\u003c/em\u003e), recent log entries, and reasons for failure if the service is not running.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eExample Command\u003c/strong\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl status apache2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#or httpd service\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl status httpd\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eOutput\u003c/strong\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eiamyaash@pi5:~ $ sudo systemctl status firewalld.service \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e● firewalld.service - firewalld - dynamic firewall daemon\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     Loaded: loaded \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e/lib/systemd/system/firewalld.service; enabled; preset: enabled\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     Active: active \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003erunning\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e since Sun 2025-06-29 20:30:48 IST; 1s ago\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       Docs: man:firewalld\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   Main PID: \u003cspan style=\"color:#ae81ff\"\u003e7956\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003efirewalld\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      Tasks: \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003elimit: 9585\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        CPU: 279ms\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     CGroup: /system.slice/firewalld.service\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e             └─7956 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eJun \u003cspan style=\"color:#ae81ff\"\u003e29\u003c/span\u003e 20:30:48 pi5 systemd\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: Starting firewalld.service - firewalld - dynamic firewall daemon...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eJun \u003cspan style=\"color:#ae81ff\"\u003e29\u003c/span\u003e 20:30:48 pi5 systemd\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: Started firewalld.service - firewalld - dynamic firewall daemon.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe output includes:\u003c/p\u003e","title":"Linux: Service Management with systemd"},{"content":"Systemd Timers A systemd timer is a moderl scheduling tool that\u0026rsquo;s part of the systemd init system used by most of the Linux distributions. Unlike cron, systemd timers can trigger tasks based not just on time, but also on events(reboot,specific service starts, when a file change, etc.).\nThey require bot a service file(defines what to run) and a timer file (defines when/how to run). Systemd timers offer advanced features like dependency management, built-in logging, resource limits, and fine-grained control over the execution environment.\nThey also ensure that only one instance of a task runs at a time, preventing overlaps, and making them ideal for complex or critical automation scenarios.\nBest for complex scheduling, dependency management, event-based triggers, and when you need robust logging and resource control.\nCron Jobs A cron job is a simple, time-based scheduler built into nearly all Unix-like operating systems. It lets you run scripts or command at specific times or intervals by editing a configuration file (crontab -e).\nCron is easy to setup and widely used for basic automation tasks like backups or log rotation, and limited logging and environment control.\nEach job runs independently, and multiple instance of the same job can overlap if ones takes too long.\nBest for simple, time-based tasks where portability and simplicity are the key.\nFile Structure .timer Filer A .timer file defines when and how a service is triggered. It works in tandem with .service file, which defines what to run.\nKey Sections and Directive:\n[Unit]: Description and dependencies [Timer]: Timing and scheduling directive. [Install]: Where to enable the timer. Important Directive OnBootSec: Run the service after a specified time interval following the system boot. (OnBootSec=5m runs 5 minutes after boot.) OnUnitActiveSec: Run the service after a specified time interval following the last activation of the unit. (OnUnitActiveSec=5s runs every hour after the last run). OnCalendar: Schedule the service to run at specific calender times(like cron; OnCalendar=*-*-* 02:00:00) Runs everyday at 2AM. AccuracySync: Allow a time window for the timer to fire (for efficiency; AccuracySync=10m timer can run anytime within 10 min window ) RandomizedDelaySec: Add a random delay to prevent many timers from running at the same time. Persistent=: If true(bool), ensures the timer runs immediately at boot if it misssed its schedules time while the system was off. Unit=: Specify which unit to activate if the service name does not match the timer name. Defining Dependency WantedBy= or Requires= in the [Install] or [Unit] section: Specifies dependencies or when the timer should be activated. Dependencies between units (services/timer): You can make one unit depend on another by using After=, Requires=, or Wants= in the [Unit] section. Example [Unit] Descriptio=My Systemd Timer [Timer] OnBootSec=5min OnUnitActiveSec=1h AccuracySec=1m RandomizedDelay=30s [Install] WantedBy=timers.target crontab File Cron itself does not have directives for dependencies or advanced scheduling, but the format is very simple.\nImportant Crontab Fields minute hour day-of-month month day-of-week command Example:\n30 2 * * * /usr/local/bin/backup.sh Defining Dependency in Cron: Cron has no built-in dependency management. Each cron job is independent. If you want ensure one job runs after another, you can use journalctl logs find out what happened. Example Automate daily backups of an important directory using systemd timers, similar to what many organizations or users do for data safety. Script File Location: /usr/local/bin/backup-docs.sh Systemd File Location: /etc/systemd/system/backup-docs.service [Unit] Description=Backups Docs Directory [Service] Type=oneshot ExecStart=/usr/loca/bin/backup-docs.sh User=username Timer File Location: /usr/systemd/system/backup-docs.timer [Unit] Description=Daily Backup of Docs Directory [Timer] OnCalendar=*-*-* 02:00:00 RandomizedDelaySec=3m Persistent=true [Install] WantedBy=timers.target Enable and Start the timer sudo systemctl daemon-reload sudo systemctl enable backup-docs.timer sudo systemctl start backup-docs.timer Verify systemctl status backup-docs.timer systemctl list-timers ","permalink":"https://docs.ayshell.dev/posts/linux/systemd/task-schedule/","summary":"Practical guide to systemd timers, covering the differences from cron, the structure of timer files, key directives, and hands-on exercises.","title":"Linux: Task Scheduling with systemd Timers"},{"content":"Anatomoy of systemd Unit File A typical systemd unit file for a service consists of three main section:\n[Unit]: Contains metadata and dependencies. [Service]: Defines how the service should be managed. [Install]: Specifies how the unit is enable or installed. [Unit] Description=My Example Service After=network.target [Service] ExecStart=/usr/bin/my-service Restart=always [Install] WantedBy=multi-user.target Important Directives ExecStart: Command to start the service. ExecStop: Command to stop the service. Restart: Policy for restarting the service (always, on-failure, on-watchdog, on-abort or no). RestartSec: Time to wait before restarting the service. (RestartSec=5s) [Service] ExecStart=/usr/bin/my-service ExecStop=/usr/bin/my-service Restart=on-failure #only restarts when failed RestartSec=8s #wait until 8 seconds to restart Defining Dependencies And Order Requires: The unit will not start unless the listed unit is active. Wants: The unit would like the listed unit to be active, but it\u0026rsquo;s not required. Before: The unit should be started before the listed unit. After: The unit should be started after the listed unit. [Unit] Description=My Custom Service Requires=custom.service After=custom.service Before=custom.service Adding Environment Variables Environment: Set environment variables directly in the unit file. EnvironmentFile: Load environment variables from a file. Environment This directive allows yout to set environment variables directly in the unit file. You can use it multiple times to set several variables. [Service] Environment=\u0026#34;VAR1=value1\u0026#34; Environment=\u0026#34;VAR2=value2\u0026#34; These variables will be available to the process started by the service.\nEnvironmentFile This directive loads environment variables from an external file. The file should contain one variable per line, in the format VAR=value. [Service] EnvironmentFile=/etc/myapp/env This is useful for sensitive data or when you want to keep variables outside the unit file.\nExample Let\u0026rsquo;s create a simple service that prints the envionment variables.\nScript: usr/loca/bin/env.sh in executable permission chmod +x !#/bin/sh echo \u0026#34;VAR1 is: ${VAR1:-not set}\u0026#34; echo \u0026#34;VAR2 is: ${VAR2:-not set}\u0026#34; Env: /usr/myapp/env VAR1=something1 VAR2=something2 Create Unit File [Unit] Description=Shows environment values [Service] ExecStart=/usr/loca/bin/env.sh #env vars; Environment Environment=\u0026#34;VAR1=something1\u0026#34; Environment=\u0026#34;VAR2=something2\u0026#34; #env file; EnvironmentFile (use it when handling sensitive data) EnvironmentFile=/etc/myapp/env [Install] WantedBy=multi-user.target Overriding Existing Services With Drop-In Configuration You can safely override or extend the configuration of existing services using drop-in files in the unit.service.d/ directory.\nUsing systemctl edit: sudo systemctl edit sshd.service This creates /etc/systemd/system/sshd.service.d/override.conf where you can add or override directives.\nManual Method: sudo mkdir -p /etc/systemd/system/sshd.service.d sudo nano /etc/systemd/system/sshd.service.d/custom.conf As systemctl edit creates the override.conf, we can manually create sshd.service.d/ and customize sshd.service.d/custom.conf. Based on the service, we want to override\nExample You want to change the restart policy of the sshd.service (the SSH daemon) so that it always restarts if it fails, without editing the original unit file. How do you achieve this using systemd drop-in files? Additionally, you want to add a custom environment variable (LOG_LEVEL=DEBUG) for the service. Create drop-in directory and file sudo systemctl edit sshd.service # open your default editor and create a file in # /etc/systemd/system/sshd.service.d/override.conf Add your overrides (In the editor, add) Restart=always Environment=\u0026#34;LOG_LEVEL=DEBUG\u0026#34; Alternatively, we can use a manual method to accomplish this without systemctl edit\nsudo mkdir -p /etc/systemd/system/sshd.service.d/ sudo nano /etc/systemd/system/sshd.service.d/override.conf #add this in the editor Restart=always Environment=\u0026#34;LOG_LEVEL=DEBUG\u0026#34; Finally, reload and restart the service\nsudo systemctl daemon-reload sudo systemctl restart sshd.service Verify using systemctl cat sshd.service\nWrite Your Own Service Unit Files: How do you create and configure a systemd unit file to run this script as a service, ensuring it start after the network is available and restarts automatically if it fails? script = /usr/loca/bin/myscript.sh (this simply greets when executed!) run this as a system service, managed by systemd Write a service in /etc/systemd/system/script-start.service: [Unit] Description=Service to start the greet script After=network.target [Service] ExecStart=/usr/local/bin/myscript.sh Restart=Always [Install] WantedBy=multi-user.target [Unit]\nDescription=Service to start the greet script Human readable description After=network.target Specifies that this service should start only after the network.target unit is active, ensuring the network is available before your script runs. [Service]\nExecStart=/usr/local/bin/myscript.sh The above script will be executed to start the service. Restart=Always Sets the restart policy so that the service will always be restarted if it stops for any reason. [Install]\nWantedBy=multi-user.target Specifies that this service should be started when the system reaches the multi-user.target state, which is standard state for a multi-user system after reboot. In simple terms, systemd creates a symbolic link so your service start at boot when you systemctl enable script-start.service. How do you set environment variables in the systemd unit file, and what directive should you use? Variable required by the script GREETING=\u0026quot;Hello, systemd!\u0026quot;. !#/bin/sh echo \u0026#34;$GREETING\u0026#34; Make sure to give execute permission to this script.\n[Unit] Description=Add env variable to service [Service] Environment=\u0026#34;GREENTING=Hello, World!\u0026#34; ExecStart=/usr/local/bin/greet.sh [Install] WantedBy=multi-user.target sudo systemctl daemon-reload reload the services for the new service to take effect. sudo systemctl enable greet.service to start the service at boot. sudo systemctl start greet.service to start for the current boot only. ","permalink":"https://docs.ayshell.dev/posts/linux/systemd/systemd-write-units/","summary":"Important directives: ExecStart, ExecStop, Restart policies; Dependencies and ordering: Requires, Wants, Before, After; Writing your own service units with examples; Overriding units using drop-in configurations (systemctl edit)","title":"Linux: Creating and Customizing systemd Units"},{"content":"Permissions and Ownership: Control who can read, write or execute files and directories. Manage user and group ownership to restric or grant access to resources. More importantly, secure sensitive data and maintain system integrity. Change Mode (chmod) chmod is used to modify the read, write and execute permissions of files and directories for the owner, group and others.\nchmod [options] [mode] [file/directory] There are two modes to pass the permissions:\nNumeric: chmod 755 file Symbolic: chmod u+x file Note: read=4, write=2, \u0026amp; execute=1; We can enter numbers in octal format for changing permissions.\nChange Owner (chown) chown is used to change the owner and/or group of a file or directory.\nchown [options] [owner][:group] [file/directory] Note: We can change the group and owner by using chmod ownerName:groupName and can change just the group by using chmod :groupName.\nChange Group (chgrp) chgrp is used to change the group ownership of a file or directory.\nsudo chgrp [options] [group] [file/directory] We don\u0026rsquo;t actually need this command in most cases, we easily do the same thing by using chown.\nSubcommands/Flags For chmod, chown \u0026amp; chgrp -R: Recursively change permissions for directories and their contents. -v: Verbose output. -c: Like verbose, but only shows files that were changes. -f: Suppress most error messages. --reference=RFILE: Set permissions to match those of a reference file. Access Control List An Access Control List (ACL) is a list of permissions or rules that specify which user or systems are granted or denied access to a particular object or system resource, such as files, directories, or network traffic.\nACLs are fundamental for security and access management in operating systems, allowing administrators to control who can read, write and execute or delete resources.\nEssential Command For filesystems, the command to view or\ngetfacl To set ACL is:\nsetfacl Subcommand (Options/Flags) getfacl -a or --access: Display the file access control list. -d or --default: Diplay the default ACL for directories -R or --recursive: Apply recursively to all files and directories. setfacl -m or --modify: Modify an existing ACL. -x or --remove: Remove an ACL entry. -b or --remove-all: Remove all extended ACL entries. -k or --remove-default: Remove the default ACL. -R or --recursive: Apply recursively. Example Viewing ACLs on a File getfacl file.ext Setting an ACL on File setfacl -m u:\u0026lt;username\u0026gt;:rwx file.ext #-m modify Setting a default ACL on a Directory setfacl -d -m u:\u0026lt;username\u0026gt;:rwx file.ext Removing an ACL Entry setfacl -x u:username /path/to/file Special Permission (Must Know!!) Each permission is assigned a numberical value; read(4), write(2), execute(1). So, when you enter the command ls -l and see the output beside the files/directories.\nYou will see something like this value, drwxrw-r--. This means, 761 in octal. d means directory. If it\u0026rsquo;s a file, it shows - hyphen instead.\nSticky Bit: When set on a directory, only the owner of a file (or root) can delete or rename files within that directory, even if others have write permission.\nSet Group ID (setgid): For directories, files/directories created within the directory will inherit the group ownership of the parent directory. For executable files, they run with the group permissions of the file\u0026rsquo;s group.\nSet User ID (setuid): For executable files, they run with the permissions of the file\u0026rsquo;s owner(often root).\nSymbolic Notation of Special Permissions Sticky Bit:\nchmod +t directory Set Group ID (setgid):\nchmod g+s dir/file Set User ID (setuid):\nchmod u+s dir/file Octal Notation of Special Permissions Sticky Bit: 1 (chmod 1777 directory) setgid: 2 (chmod 2777 directory) setuid: 4 (chmod 4777 directory) Summary Table Permission Symbolic Notation Octal Notation Sticky Bit chmod +t chmod 1777 setgid chmod g+s chmod 2777 setuid chmod u+s chmod 4777 ","permalink":"https://docs.ayshell.dev/posts/linux/manage-file-permissions/","summary":"This guide explains how to use Linux commands to manage file permissions, ownership and special permissions. Commands: chmod, chown, and chgrp.","title":"Linux: Manage File Permissions"},{"content":"Permanently Mounting The Disk Find the UUID of the Device: lsblk -f #displays the UUID sudo blkid #displays the UUID Create a Mount Point: sudo mkdir /mnt/permanent-mount Edit the /etc/fstab: sudo nvim /etc/fstab Add this line at the bottom:\nUUID=your-uuid-here /mnt/permanent-storage ext4 defaults 0 2 Replace your-uuid-here with the actual UUID from step 1. Replace /mnt/permanent-storage with your mount point. Replace ext4 with your filesystem type if different. defaults are standard mount options. 0 means the partition will not be backed up with the dump utility. 2 means the partition will be checked by fsck after the root filesystem. Test the Mount Before Rebooting: sudo mount -a Temporarily Mounting The Disk Create a Mount Point and Mount the Disk Here: sudo mkdir /mnt/temp-storage #make sure to create directory and it can be created and mounted anywhere sudo mount /dev/sda1 /mnt/temp-storage Note: Never unplug/remove the device without un-mounting it from the system.\nsudo umount /mnt/temp-storage ","permalink":"https://docs.ayshell.dev/posts/linux/mount-unmount/","summary":"Know how to mount and unmount storage effectively for temporary and permanent storage.","title":"Linux: How To Mount And Un-Mount Permanently/Temporarily"},{"content":"What is umask? The umask command sets the default permissions for newly created files and directories.\nIt acts as a \u0026ldquo;mask\u0026rdquo; that subtracts specified permissions from the maximum permissions, ensuring new files and directories are created with secure defaults. It\u0026rsquo;s also a process-based tool, which sets the default permission as long as it\u0026rsquo;s running in the background.\nEssential Commands Commands Description umask Check the current umask value umask 022 Set the new umask value umask u=rwx, g=rx, o=r Sets permission using symbolic notation (equivalent to 022) Subcommands Commands Description umask -S Print mask in symbolic form umask -p Print mask as command for reuse Example Change umask to 027 and create a new file: iamyaash@pi5:~/umask $ umask 0022 iamyaash@pi5:~/umask $ touch testFile.txt iamyaash@pi5:~/umask $ ll total 0 -rw-r--r-- 1 iamyaash iamyaash 0 Jun 25 11:43 testFile.txt iamyaash@pi5:~/umask $ umask 027 \u0026amp;\u0026amp; umask 0027 iamyaash@pi5:~/umask $ touch testFile_027.txt iamyaash@pi5:~/umask $ ll total 0 -rw-r----- 1 iamyaash iamyaash 0 Jun 25 11:43 testFile_027.txt -rw-r--r-- 1 iamyaash iamyaash 0 Jun 25 11:43 testFile.txt Change umask to 077 and create a directory: iamyaash@pi5:~/umask $ ll total 0 iamyaash@pi5:~/umask $ umask 0022 iamyaash@pi5:~/umask $ mkdir testDir022 \u0026amp;\u0026amp; ll total 4.0K drwxr-xr-x 2 iamyaash iamyaash 4.0K Jun 25 11:48 testDir022 iamyaash@pi5:~/umask $ umask 077 \u0026amp;\u0026amp; umask \u0026amp;\u0026amp; mkdir testDir077 \u0026amp;\u0026amp; ll 0077 total 8.0K drwxr-xr-x 2 iamyaash iamyaash 4.0K Jun 25 11:48 testDir022 drwx------ 2 iamyaash iamyaash 4.0K Jun 25 11:48 testDir077 What is chgrp? The chgrp is a Linux command that changes the group ownership of the files and directories.\nEssential Commands Commands Description chgrp groupName directoryName Change the group ownership of a file chgrp -R groupName directoryName Change the group ownership of both the directory and the contents inside it Subcommands Commands Description chgrp -R Recursive Operations chgrp -v Verbose output details chgrp --reference=referenceFile/Dir targetFile To change the group ownership like the referenced file/directory Example List your groups groups Change the group of a file/directory chgrp groupName fileName.txt #file chgrp groupName dirName/ #directory only, not the contents inside it chgrp groupName -R dirName/ #directory and it\u0026#39;s content ","permalink":"https://docs.ayshell.dev/posts/linux/umask-chgrp/","summary":"To ensure that new files created in a shared directory are automatically assigned to the directory’s group rather than the group of the user who created them.","title":"Linux: Assigning Permissions and Group Ownership Automatically For Newly Created Files \u0026 Directories (umask \u0026 chgrp)"},{"content":"1. What is Firewalls in Linux? A firewall is a set of rules for controlling the incoming and outgoing network traffic based on criteria like IP address, port, and protocol. Linux offers multiple tools for firewall management with firewalld and iptables being the most common.\n2. Key Concepts Zones (firewalld): Logical groupings of rules that define the trust level of network connections (e.g., public, home, work) Ports: Numeric endpoints for network services (e.g., 80 for HTTP, 22 for SSH) Protocols: The type of network traffic (e.g., TCP, UDP) ACCEPT/DROP: ACCEPT: Allows traffic DROP: Silently discards traffic (no response to sender) Permanent vs Runtime Rules: Runtime: Active until reboot or reload. Permanent: Saves and applied after reboot. 3 Using firewalld firewalld is a dynamic firewall manager that uses zones and services for easier configuration.\nBasic Commands List all current rules: firewall-cmd --list-all Add a service (eg: SSH) firewall-cmd add-service=ssh --permanent Remove a service firewall-cmd --remove-service=ssh --permanent Add a port (eg: HTTP, port 80) firewall-cmd --add-port=80/tcp --permanent #use --remove-port=80/tcp --permanent to remove the HTTP and port. Reload to apply changes firewall-cmd --reload Set default zone firewall-cmd --set-default-zone=public Add a rich rule to allow only a specific IP firewall-cmd --permanent --zone=public --add-rich-rule=\u0026#39;rule family=\u0026#34;ipv4\u0026#34; source address=\u0026#34;192.168.31.100\u0026#34; accept\u0026#39; 4. Using iptables iptables provides fine-grained control over firewall rules but has a steeper learning curve.\nBasic Commands List current rules iptables -L Allow incoming SSH (Port 22) iptables -A INPUT -p tcp -dport 22 -j ACCEPT Allow incoming HTTP (Port 80) iptables -A INPUT -p tcp --dport 80 -j ACCEPT Drop all incoming traffic iptables -A INPUT -j DROP Save rules (using iptables-save) iptables-save \u0026gt; /etc/sysconfig/iptables Restore rules iptables-restore \u0026lt; /etc/sysconfig/iptables Exercies Open and close ports with firewalld Open port 80 for HTTP: firewall-cmd --add-port=80/tcp --permanent firewall-cmd --reload #to reflect the changes Close port 80 firewall-cmd --remove-port=80/tcp --permanent firewall-cmd --reload Make sure to use --reload to reflect changes all over the device.\nAllow/Deny services with firewalld firewall-cmd --add-service=ssh --permanent #allow/add the service firewall-cmd --reload firewall-cmd --remove-service=ssh --permanent #deny/remove the service firewall-cmd --reload Secure system by allowing only trusted IP firewall-cmd --permanent --zone=public --add-rich-rule=\u0026#39;rule family=\u0026#34;ipv4\u0026#34; source address=\u0026#34;192.168.31.100\u0026#34; service name=\u0026#34;ssh\u0026#34; accept\u0026#39; firewall-cmd --reload Purpose: Adds a rich rule to the public zone of the firewall, allowing only the IP address 192.168.31.100 to access the SSH service (port 22 by default) over IPV4. All other IPs attempting to connect SSH will be blocked unless another rules is specified for that IP address.\n--permanent ensures the rules are saved even after reboot or service restart. --zone=public specifies the zone where the rule is added. The public zone is typically used for interfaces exposed to the internet or untrusted networks. So blocking other IPs except the specified IP actually makes sense. --add-rich-rule adds a rich rule, which allows for more complex and granular firewall configurations than simple port or service rules. rule family=\u0026quot;ipv4\u0026quot; specifies this rules only applies to IPV4 traffic. source address=\u0026quot;192.168.31.100\u0026quot; restricts the rule to traffic originating from the IP address. service name=\u0026quot;ssh\u0026quot; applies the rule to the SSH service (port 22). accept allows the matching traffic. (ACCEPT/DROP\u0026hellip;) Setup basic rules with iptables iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -j DROP Use this command, in case you want to save the rules.\niptables-save \u0026gt; /etc/sysconfig/iptables Monitor firewall logs journalctl -xe | grep firewalld journalctl -xe | grep iptables ","permalink":"https://docs.ayshell.dev/posts/linux/firewalld/firewalld/","summary":"Firewalls in Linux system administration, focussing on both firewalld and iptables.","title":"Linux: firewalld \u0026 iptables"},{"content":"What is dd? The dd command is a powerful utility in Linux used for copying and converting data at the block level, often employed for tasks like creating disk images, cloning disks, securely wiping data, and more.\nEssential Commands and Subcommands Note: dd command uses operands that how data is read, written, or converted.\nOption Description if= Input file (source) of= Output file (destination) bs= Block size for reading/writing(eg:1M for 1 megabytes) count= Number of blocks to coyp skip= Skip a specified number of blocks at the start of the input seek= Skip a specified number of blocks at the start of the output status= Control progress display(progres, noxfer, none) conv= Apply data conversions (eg: sync, noerror, notrunc) iflag= Input flags (eg: direct, fullblock) oflag= Output flags (eg: direct, sync) Exercises Create a file filled with zeros: dd if=/dev/zero of=file.txt bs=1M count=100 Copy a disk partition to a file: dd if=/dev/sda1 of=backup.img bs=4M Restore a disk image to a partition: dd if=backup.img of=/dev/sda1 bs=4M Create a bootable USB drive: dd if=ubuntu.iso of=/dev/sdb bs=4M status=progresser Copy only part of a file: dd if=/dev/zero of=largefile.img bs=1M count=10 #create a file with zeros dd if=largefile.img of=partfile.img bs=1M count=1 #let copy part of the file for 1mb Wipe a File(Overwrite with zeros/randomly): dd if=/dev/zero of=partfile.img bs=1M #keep on filling zero until it reaches the original size of the file dd if=/dev/urandom of=partfile.img bs=1M #keeps filling random data until it reaches the original size of the file Backup the Master Boot Record (MBR) sudo dd if=/dev/sda of=mbr_backup.img bs=512 count=1 Restore the Master Boot Record from Backup sudo dd if=mbr_backup.img of=/dev/sda bs=512 count=1 Monitor Progress of a Large Copy dd if=largefile.img of=largefile_copy.img bs=1M status=progress ","permalink":"https://docs.ayshell.dev/posts/linux/tools/dd-util/","summary":"dd is a Linux tool, and it widely used for Linux system administration and is essential for many low-level tasks involving disks, partitions, and files at the block level.","title":"Linux Tools: dd Utility Tool"},{"content":"1. Understanding Linux Logging Systems journalctl is a tool to interact with journald which is an in-built tool in systemd. It helps logging easy and accessible because it was stored in binary format managed by journald. But, the traditional logs are stored in plain text files under /var/log/.\nsystemd Journal It centralizes logs in a binary format managed by journald, accessible via journalctl. Offers advanced filtering, real-time updates, and more context.\nTraditional Logs Stores logs in a plain text files under /var/logs/. We have to use external tools like grep, tail, and less for analysis. It is still functional, but very old and there\u0026rsquo;s no advanced filtering.\n2. Using journalctl to View and Filter Logs journalctl Centralizes logs from the kernel, systemd, and services in a structured, searchable binary format. Provides advanced filtering, real-time monitoring, and boot-specific logs. Designed to overcome the limitations of tradition plain-text logging by offering more context and metadata. Subcommands and Essential Commands Command Description journalctl View all system logs (Chronological Order) journalctl -r View logs in reverse chronological order (newest first) journalctl -n N Show the last N entries journalctl -k Show only kernel messages journalctl -p LEVEL Filter by log priority(e.g: error or 3) journalctl -u UNIT Filter by systemd unit/service(e.g: apache2.service) journalctl -f Follow logs in real time (aka tail -f) journalctl --since TIME Show logs since a specific (Time) Sun Jun 22 14:44:52 2025 journalctl --until TIME Show logs until a specific time journalctl --disk-usage Show disk usage of journal logs journalctl --vacuum-size=SIZE Reduce logs size to specific amount journalctl _SYSTEMD_UNIT=UNIT Filter by systemd unit using field (aka -u) journalct _UID=UID Filter by user ID Traditional Logs Stores traditional system logs in plain text files. Used for compatibility with tools and scripts. Allows quick access to logs for specific applications or subsystems Not as much flexible as journald Subcommand and Essential Commands Log File Description /var/log/message/ General System Messages /var/log/syslog (Debian*) System Logs for Debian based distro and it\u0026rsquo;s similar to message /var/log/auth.log Login attempts, sudo, ssh (/var/log/secure on RHEL/Fedora) /var/log/kern.log Kernel Messages /var/log/dmesg Boot-time Kernel Messages /var/log/httpd/, /var/log/nginx/ Web Server Logs Example View all system logs journalctl View logs in reverse order journalctl -r Show only kernel messages journalctl -k View logs from the current boot journalctl -b Filter by priority (Error and Above) journalctl -p err # other flags: emerg,alert,crit,warning,notice,info,debugs Filter by service journalctl -u ssh.service Show last 20 log entries journalctl -n 20 Output in SON format journalctl -o json-pretty Monitor logs in real-time journalctl -f Investigate failed login attempts journalctl | grep -i \u0026#34;failed password\u0026#34; journalctl -u ssh.service | grep -i \u0026#34;failed password\u0026#34; #show failed login attempts for specific service Track system errors over time and period journalctl --since \u0026#34;2025-06-24 08:08:08\u0026#34; --until \u0026#34;2025-06-24 17:17:17\u0026#34; -p err Mostly useful for post-analysis\nView logs for a specific user journalctl _UID=$(id -u) Export logs for analysis journalctl --since yesterday \u0026gt; textFile_logs.txt Filter by Process ID journalctl _PID=\u0026lt;pid\u0026gt; ","permalink":"https://docs.ayshell.dev/posts/linux/journald/journalctl/","summary":"Understanding Linux log locations, using journalctl, analyzing traditional logs, filtering and searching logs with grep, less and time filters.","title":"Linux: Log Analysis and Journals"},{"content":"Networking in Linux 1. ip Command The ip command is a modern tool for managing network interfaces, IP addresses, and routing tables. It replaces older tools like ifconfig and is part of the iproute2 suite.\nEssential Commands ip link: Show and manage network interfaces.\nip address(ip a, ip addr): Show and manage IP addresses.\nip route (ip r): Show and manage routing tables.\nUsage Command Description ip link List all network interfaces and their status ip addr Show IP addresses assigned to interfaces ip route Show the routing table sudo ip link set \u0026lt;interface\u0026gt; up | down Bring an interface up or down sudo ip addr add \u0026lt;IP\u0026gt;/\u0026lt;mask\u0026gt; dev \u0026lt;interface\u0026gt; Add an IP addresses to an interface (gets reset after reboot) Example Find you gateway and try adding static IP route ip route # make sure to copy the IP address that start after \u0026#34;default via\u0026#34; (that\u0026#39;s the default gateway of your network) sudo ip route add 192.168.31.13 via 192.168.31.1 List all network interfaces and note their names ip link Check the current IP address of your main interface ip r #to display the current network interface and it will you show you the ip address as well ip a #to display all the network interface Display the routing table and identify your default gateway ip r # the IP address that\u0026#39;s showed after \u0026#34;default via\u0026#34; is your default gateway address 2. ss Command ss is a tool to monitor network sockets and connections. It is faster and more informative than netstat and is preferred in modern Linux systems.\nEssential Commands ss -a: Show all sockets (listening and established).\nss -l: Show only listening sockets.\nss -n: Show numerical addresses instead of resolving hostnames.\nss -p: Show the process using the socket.\nss -t: Show TCP connections.\nss -u: Show UDP connections.\nUsage Commands Description ss -a List all listening and established connections ss -lt List only listening TCP sockets ss -t -p Show all TCP connections with process information ss -u Show all UDP connections Example List all listening TCP ports on your system. ss -lt #l shows only listening sockets #t show only the listening TCP sockets Find out which process is using port 88 (SSH) ss -pa | grep \u0026#34;:88\u0026#34; #filter both listening and non-listening sockets ss -tuln | grep \u0026#34;:88\u0026#34; #more specific List all established TCP connections ss -at 3. netstat Command netstat is a legacy tool for displaying network connections, routing tables, and interface statistic. It is less efficient than ss but still useful.\nEssential Commands netstat -a: Show all sockets.\nnetstat -n: Show numerical addresses.\nnetstat -t: Show TCP connections.\nnetstat -u: Show UDP connections.\nnetstat -r: Show routing table.\nnetstat -i: Show network interface statistic.\nUsage Commands Description netstat -a Show all sockets netstat -at Show all TCP connections netstat -r Show routing table netstat -au Show all UDP connections netstat -i Show network interface statistic Example List all active network connections netstat -a Display the routing table netstat -r Check statistics for your network interfaces netstat -i 4. ping Command ping is used to test connectivity between your system and another host on the network. In simple terms, ping command is used to test if a host is reachable.\nEssential Commands ping -c: Number of packets to send.\nping -i: Interval between packets.\nping -s: Packet size.\nUsage Command Description ping google.com Ping a host (it\u0026rsquo;s continuous by default, stop with CTRL+C) ping -c 4 bing.com Send only 4 packets ping -i 2 bing.com Change the interval between packets ping -s 100 bing.com Specify packet size Example Ping bing.com and observe the output ping bing.com #stop with CTRL+C after some time Ping you local gateway ping 192.168.31.1 Send 5 packets with a 3 second interval to a known IP ping -i 2 -c 4 192.168.61.123 Bonus traceroute Command traceroute traces the path packets take to reach a destination, showing each hop and the response time. It helps identify where a connection slows or fails.\nEssential Commands -m: Set the maximum number of hops. (aka ping -c) (traceroute -m 10 bing.com)\n-n: Show IP addresses instead of hostnames (traceroute -n bing.com)\n-I: ICMP echo requests instead of UDP (traceroute -I bing.com)\n-w: Set timeout for each probe (traceroute -w 2 bing.com)\nExample Trace the route to bing.com and note number of hops traceroute bing.com #output traceroute to bing.com (2620:1ec:33::10), 30 hops max, 80 byte packets Repeat with the -n option to see only IP addresses. traceroute -n Limit the trace 8 hops traceroute -m 8 bing.com dig and nslookup These tools query DNS records, helping you check domain resolution and DNS server usage.\ndig Usage dig bing.com Subcommands +short: Shows only the answer (dig bing.com +short) +trace: Trace the DNS query path from the root servers down to the authoritative server for the domain (dig bing.com +trace) nslookup Usage nslookup bing.com This returns the resolved IP address and the DNS server used for the lookup.\nInteractive Mode:\nnslookup \u0026gt; google.com \u0026gt; set type=mx \u0026gt; google.com \u0026gt; exit ","permalink":"https://docs.ayshell.dev/posts/linux/networking-tools/","summary":"Linux networking tools for system administration: ip, ss, netstat, ping, and more.","title":"Linux: Networking Tools"},{"content":"What is systemd? systemd is the init system and service manager used in most Linux distributions (Fedora, Ubuntu, Arch, etc). It is the first process (PID 1) that runs after the kernel boots and is responsible for bringing up the rest of the system.\nIt is designed to provide a robust framework for managing the system\u0026rsquo;s lifecycle, starting from early boot and continuing until system shutdown.\nRole and Functionality of systemd? PID 1 Process systemd runs as the first process during the boot sequence, orchestrated by the Linux kernel. All the other user-space processes are started directly by systemd or it\u0026rsquo;s child processes.\nService Management systemd manages the startup, shutdown, monitoring, and lifecycle of system services. It replaces older init systems like SysV init and offer backward compatibility with traditional init scripts.\nParallelization Unlike traditional init systems that starts services one second after another, systemd can start services in parallel, significantly reducing boot times.\nDependency Management systemd handles dependencies between services and other system resources, ensuring that services start in the correct order and only when required.\nResource Management It uses Linux control groups (cgroups) to track and manage system resources, providing better control and isolation of processes.\nLogging systemd includes a built-in logging mechanism called journalctl, which collects and manages logs from all system services, making troubleshooting easier.\nList of Commands Action Command Example Description / Usage Extra Commands \u0026amp; Tips for Beginners Start a service sudo systemctl start Starts the specified service immediately systemctl status (check if running) Stop a service sudo systemctl stop Stops the specified service immediately systemctl is-active (check if stopped) Restart a service sudo systemctl restart Restarts the specified service Reload a service sudo systemctl reload Reloads configuration without full restart Enable a service sudo systemctl enable Enables the service to start at boot systemctl is-enabled (check enabled) Disable a service sudo systemctl disable Disables the service from starting at boot Check service status systemctl status Shows detailed status of the service Check if active systemctl is-active Returns \u0026ldquo;active\u0026rdquo; or \u0026ldquo;inactive\u0026rdquo; for the service Check if enabled systemctl is-enabled Returns \u0026ldquo;enabled\u0026rdquo; or \u0026ldquo;disabled\u0026rdquo; for the service Mask a service sudo systemctl mask Prevents a service from starting, even manually sudo systemctl unmask (to undo) Show service info systemctl show Displays detailed properties of the service systemctl show -p List dependencies systemctl list-dependencies Lists units that depend on or are required by this service --before and --after flags for order[1][2] List all services systemctl list-units --type=service Lists all active service units Reload systemd sudo systemctl daemon-reload Reloads all unit files and updates systemd after changes What is journalctl? journalctl is the primary command-line tool for viewing and managing logs collected by systemd\u0026rsquo;s journald service. Instead of traditional plain-text log files are created around the system, systemd centralizes logs in structured, binary format, making it easier to search, filter and analyze system and application events.\n1. Viewing and Following Logs Command Example Description / Purpose journalctl View all logs journalctl -f Follow (tail) logs in real-time 2. Filtering Logs by Service Command Example Description / Purpose journalctl -u View logs for a specific service 3. Filtering Logs by Time and Boot Command Example Description / Purpose journalctl -n Show the last N log entries journalctl --since \u0026quot;\u0026quot; Show logs since a specific time journalctl -b Show logs from the current boot journalctl -b -1 Show logs from the previous boot 4. Filtering Logs by Priority and Content Command Example Description / Purpose journalctl -r Show logs in reverse order (newest first) journalctl -p Filter by log priority (e.g., -p err, -p info) journalctl -g \u0026quot;\u0026quot; Search logs for a pattern journalctl _PID= Show logs for a specific process ID 5. Output Formatting Command Example Description / Purpose journalctl -o json Output logs in JSON format journalctl -o cat Output only the message content (no metadata) journalctl --no-pager Dump logs directly to terminal (no pager) 6. Maintenance and Disk Usage Command Example Description / Purpose journalctl --disk-usage Show journal disk usage sudo journalctl --vacuum-time= Remove logs older than specified time Units, Services \u0026amp; Target What is Units? A unit is any resource that systemd can manage. Each unit is described by a configuration file(aka unit file) with a specific extension indicating its type.\nCommon Units .service .target .socket .device .mount .automount, .swap, .path, .timer, .slice, and .scope Example A unit file can be,\netc/systemd/system/example.service (service unit), etc/systemd/system/my-mount.mount (mount unit), etc/systemd/system/daily-backup.time (time unit) What is Services? A service unit (.service) is used to manage applications or daemons running on the system. It defines how to start, stop, restart, or reload a service, and it\u0026rsquo;s dependencies.\nExample A simple service unit file for a custom script (/etc/systemd/system/myscript.service):\n[Unit] Description= My Custom Script Service [Service] ExecStart=/usr/loca/bin/myscript.sh [Install] WantedBy=multi-user.target What is Targets? A target unit (.target) is a group of units used to synchronize the system\u0026rsquo;s state. Targets are used to bring the system to a specific state, such as booting to a graphical or multi-user environment.\nCommon Targets multi-user.target: System is ready for multiple users, but without a graphical interface. graphical.target: System is ready for multiple users with a graphical interface. rescue.target: System is in single-user rescue mode. Example: The multi-user.target is a standard target for non-graphical, multi-user system. When the system boots, it tries to reach this target, starting all services that are required for this state.\nSummary of Units, Services \u0026amp; Target Unit Type Example Name Purpose/Example Use service myscript.service Manages a custom script or application target multi-user.target Groups services for multi-user, non-graphical boot socket sshd.socket Activates a service when a network connection arrives device dev-sda5.device Manages a hardware device mount mnt-data.mount Manages a filesystem mount point timer daily-backup.timer Schedules tasks (like cron jobs) ","permalink":"https://docs.ayshell.dev/posts/linux/systemd/systemd-service-management/","summary":"What is systemd and how it works? What are units, services, targets in systemd? Essential commands like systemctl \u0026amp; journalctl, and creating \u0026amp; managing custom services.","title":"Linux: Systemd And Service Management"},{"content":"Let\u0026rsquo;s Make Emacs Faster! 1. Find The systemd Service File For emacs sudo find / -iname emacs.service #output iamyaash@fedora:~/Projects/gh/iamyaash/spells$ sudo find / -iname emacs.service [sudo] password for iamyaash: /sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/emacs.service /usr/lib/systemd/user/emacs.service cd /usr/lib/systemd/user 2. Verify emacs.service, Whether It\u0026rsquo;s Set To Run emacs --daemon iamyaash@fedora:~ $ cat /usr/lib/systemd/user/emacs.service [Unit] Description=Emacs text editor Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ [Service] Type=notify ExecStart=/usr/bin/emacs --fg-daemon # Emacs will exit with status 15 after having received SIGTERM, which # is the default \u0026#34;KillSignal\u0026#34; value systemd uses to stop services. SuccessExitStatus=15 # The location of the SSH auth socket varies by distribution, and some # set it from PAM, so don\u0026#39;t override by default. # Environment=SSH_AUTH_SOCK=%t/keyring/ssh Restart=on-failure [Install] WantedBy=default.target This service run the emacs and as long as it runs the daemon it\u0026rsquo;s fine!\n3. Let\u0026rsquo;s enable \u0026amp; start This Service systemctl --user enable emacs.service systemctl --user start emacs.service The service file is under the /systemd/user directory, we must have to use the --user flag while executing the command.\nNote: Make sure to kill any emacs processes in the background or else it won\u0026rsquo;t run!\nps aux | grep emacs ## or ps -ef | grep emacs killall emacs kill \u0026lt;pid\u0026gt; 4. Set Alias for emacsclient For Terminal Execution nvim ~/.bashrc alias emacscl=\u0026#34;emacsclient -c -a \u0026#39;emacs\u0026#39;\u0026#34; source ~/.bashrc 5. Create a Desktop Icon for GUI Execution sudo find / -iname emacs.desktop Duplicate the existing desktop file:\nsudo cp /usr/share/applications/emacs.desktop /usr/share/applications/emacsclient.desktop Modify configurations inside the emacsclient.desktop:\n#replace Name \u0026amp; Exec only Name=Emacsclient Exec=emacsclient -c -a \u0026#39;emacs\u0026#39; %F Alternate If you do not want the daemon to run automatically when the device boots, but instead want to start it manually whenever needed, you can simply use scripts to handle this.\nemacs server (daemon) Note: Make sure to store the scripts safe and secure!\ntouch emacs-server.sh nvim emacs-server.sh Paste this into emacs server.sh:\n#!/bin/bash echo \u0026#34;Initializing \\`emacs --daemon\\` server\u0026#34; /usr/bin/emacs --daemon emacs client (client) touch emacs-client.sh nvim emacs-client.sh Paste this into emacs-client.sh:\n#!/bin/bash echo \u0026#34;Opening emacs client \\`emasclient -c -a \u0026#39;emacs\u0026#39;\\`\u0026#34; emacsclient -c -a \u0026#39;emacs\u0026#39; Change Permissions for Execution chmod 755 emacs-server.sh emacs-client.sh Summary With this setup, the emacs --daemon runs in the background and can execute tasks instantly when using emacsclient. Suitable for people who use emacs as a daily driver and in need of speeding things up!\n","permalink":"https://docs.ayshell.dev/posts/emacs/emacs-daemon/","summary":"Running an Emacs daemon server in the background and using emacsclient instead of a standalone application helps make opening, closing, and other operations faster.","title":"Emacs: Daemon \u0026 Client Automation"},{"content":"1. Understanding File Systems What is a File System? A file system controls how data is stored and retrived. Without a file system, the OS wouldn\u0026rsquo;t know where a file starts or ends.\nCommon Linux File Systems File System Description ext4 Default for many Linux distros; journaling support xfs High-performance; good for large files btrfs Copy-on-write, snapshots, RAID built-in vfat Compatible with Windows, for USB drives ntfs Windows file system; needs special driver in Linux 2.Listing Disks and Paritions This displays all disks and partitions in a tree-like format, showing relationships between devices and their mount points.\nCommand Example What it does lsblk List all block devices (tree format) lsblk -a Include empty devices lsblk -f Show filesystem info (type, label, UUID) lsblk -b Show sizes in bytes lsblk -l Output as a list (not tree) lsblk --output NAME,SIZE,TYPE Show only specific columns Example Output:\niamyaash@fedora:~/ $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS zram0 251:0 0 8G 0 disk [SWAP] nvme0n1 259:0 0 476.9G 0 disk ├─nvme0n1p1 259:1 0 100M 0 part /boot/efi ├─nvme0n1p2 259:2 0 16M 0 part ├─nvme0n1p3 259:3 0 174.7G 0 part ├─nvme0n1p4 259:4 0 1G 0 part ├─nvme0n1p5 259:5 0 1G 0 part /boot └─nvme0n1p6 259:6 0 300.1G 0 part /home / nvme0n1 is your disk and nvme0n1p1\u0026hellip;nvme0n1p6 are partitions of a single disk.\n3. Checking Disk Usage df (Disk Free) The df (disk free) command is used to display information about the available and used disk space on all mounted filesystems.\nShows mounted file systems in human readable output and their usage:\ndf -h Example Output:\niamyaash@fedora:~ $ df -h Filesystem Size Used Avail Use% Mounted on /dev/nvme0n1p6 301G 38G 262G 13% / devtmpfs 4.0M 0 4.0M 0% /dev tmpfs 7.6G 32K 7.6G 1% /dev/shm efivarfs 128K 46K 78K 38% /sys/firmware/efi/efivars tmpfs 3.1G 2.2M 3.1G 1% /run tmpfs 1.0M 0 1.0M 0% /run/credentials/systemd-journald.service tmpfs 7.6G 2.9M 7.6G 1% /tmp /dev/nvme0n1p6 301G 38G 262G 13% /home /dev/nvme0n1p5 974M 474M 433M 53% /boot /dev/nvme0n1p1 96M 47M 50M 49% /boot/efi tmpfs 1.0M 0 1.0M 0% /run/credentials/systemd-resolved.service tmpfs 1.6G 3.8M 1.5G 1% /run/user/1000 List of df Commands Command Example What it does df Shows disk space for all mounted filesystems df -h Human-readable output (KB, MB, GB) df -Th Human-readable with filesystem type df /home/user Filesystem info for /home/user df -i Shows inode usage df -x tmpfs Excludes tmpfs filesystems df -Tt ext4 Only shows ext4 filesystems df --output=source,avail,pcent Custom columns (filesystem, available, use%) df -aTh All filesystems, with type and human-readable Note: The df command shows information about the filesystem’s available and used space, not the size or usage of individual files. If you use df filename.ext, it will display which filesystem contains the file and how much space is available on that filesystem, but it never shows properties or the actual size of the file itself.\ndu (Disk Usage) The du (disk usage) command is a fundamental Linux tool for checking how much space files and directories occupy.\n#top space-consuming directories #folder-by-folder view du -sh * # use .(dot), *(asterisk), (~)tilde... as exercise #output iamyaash@fedora:~$ du -sh * 4.0K Desktop 208M Documents 2.5G Downloads 660M Games 3.1G go 238M KDE Vaults 0 Music 134M Pictures 4.4G Projects 0 Public 4.0K Scripts 0 Templates 0 Videos List of du Commands Command What it does du Usage of current directory du /home/user Usage of /home/user du -h /home/user Usage in human-readable format du -sh /home/user Total usage of /home/user du -ah /home/user All files/dirs (including hidden) in /home/user du -c /home/user Total for all listed directories du -d 1 /home/user First-level subdirectories only du --exclude=\u0026quot;*.log\u0026quot; /home/user Exclude .log files du -BM directory_name Displays the size in megabytes(MB) du -h file.txt Shows the size of a single file du -h /home/user | sort -h Pipe to sort for sorted results 4. Mounting and Unmounting Drives Mounting connects a storage device (like a hard drive partition) to a directory in Linux so you can access its contents.\nExample:\nsudo mount /dev/nvme0n1p6 /mnt This makes /dev/nvme0n1p6 available at /mnt.\nYou can use any empty directory instead of /mnt.\nUnmounting safely removes access:\nsudo umount /mnt Tip: Always unmount before removing the device!\n5. Creating File Systems To format a partition with a file system:\next4:\nsudo mkfs.ext4 /dev/nvme0n1p6 xfs:\nsudo mkfs.xfs /dev/nvme0n1p6 Obviously, it\u0026rsquo;s gonna erase all the data on the partition.\n6. Mount On Boot Using /etc/fstab To mount partitions automatically at boot: /etc/fstab\nThe /etc/fstab file is a configuration file that tells your Linux system which partitions to mount automatically at boot, where to mount them, and with what options. Each line in the file describes one filesystem and its mounting details.\nFormat of an /etc/fstab Entry Each line has six fields, separated by spaces or tabs:\n\u0026lt;device\u0026gt; \u0026lt;mount point\u0026gt; \u0026lt;filesystem type\u0026gt; \u0026lt;options\u0026gt; \u0026lt;dump\u0026gt; \u0026lt;pass\u0026gt; Device: The storage device (e.g., /dev/sda1, UUID=..., or LABEL=...) Mount point: Directory where the device will be mounted (e.g., /mnt/data) Filesystem type: Type of filesystem (e.g., ext4, ntfs, xfs) Options: Mount options (e.g., defaults, ro, noatime) Dump: Backup flag (use 0 if you don’t use the dump tool) Pass: Filesystem check order (use 0 to disable, 1 for root, 2 for others) Example Entry Suppose you want to automatically mount an ext4 partition with UUID 1234-5678 to /mnt/data at boot. Add this line to /etc/fstab:\nUUID=1234-5678 /mnt/data ext4 defaults 0 2 Note: Always use UUID or LABEL instead of /dev/sdXY to avoid issues if device names change. You can find the UUID of your partitions with lsblk -f or blkid.\n7. Checking Disk Health It needs smartmontools, which is installed on most of the Linux distros.\nsudo smartctl -a /dev/nvme0n1p6 List of Commands Command Purpose lsblk List block devices df -h Disk space usage mount/umount Mount and unmount partitions mkfs.ext4 Format with ext4 lsblk -f Show FS type, UUID blkid Show UUID and label /etc/fstab Persistent mount config du -sh * Directory sizes ","permalink":"https://docs.ayshell.dev/posts/linux/file-systems-storage/","summary":"How to manage file systems and storage in Linux operating systems.","title":"Linux: File Systems And Storage"},{"content":"Permission Groups: Owner - Permissions for who owns the file/directory. Group - Permissions that applies to the group assigned to the file/directory. Others - Permissions that all the other users have. Each permission group gets 3 permission that is read, write and execute. To learn how these 3 permissions work, we have to look into an example: Lets ls -l or ll (in Fedora based distro) to display the list of current directory.\niamyaash@fedora:~/iamyaash/spells$ ls -l total 4 drwxr-xr-x. 1 iamyaash iamyaash 20 Jun 12 20:57 archetypes drwxr-xr-x. 1 iamyaash iamyaash 28 Jun 12 20:57 content -rw-r--r--. 1 iamyaash iamyaash 881 Jun 12 20:57 hugo.yaml drwxr-xr-x. 1 iamyaash iamyaash 178 Jun 12 20:57 public drwxr-xr-x. 1 iamyaash iamyaash 56 Jun 13 19:28 scripts drwxr-xr-x. 1 iamyaash iamyaash 16 Jun 12 20:57 themes Directory:\ndrwxr-xr-x. 1 iamyaash iamyaash 56 Jun 13 19:28 scripts File:\n-rw-r--r--. 1 iamyaash iamyaash 881 Jun 12 20:57 hugo.yaml File Type \u0026amp; Permissions Number of Hard Links Owner Name Group Name Size (Bytes) Last Modified Date \u0026amp; Time Name drwxr-xr-x. 1 iamyaash iamyaash 56 Jun 13 19:28 scripts Detailed Breakdown 1. File Type \u0026amp; Permissions (drwxr-xr-x.) d: Directory (type of file) Other possible types: - = Regular file l = Symbolic link c = Character device b = Block device rwxr-xr-x: Permissions (read, write, execute) First 3 (rwx): Owner (user) permissions r = read w = write x = execute Next 3 (r-x): Group permissions r = read - = no write x = execute Last 3 (r-x): Others (everyone else) permissions r = read - = no write x = execute 2. Number of Hard Links (1) Count of hard links pointing to this file/directory. 3. Owner Name (iamyaash) Username of the file/directory owner. 4. Group Name (iamyaash) Group name that owns the file/directory. 5. Size (Bytes) (56) Size of the file/directory in bytes. (For directories, this is the size of the directory metadata, not contents.) 6. Last Modified Date \u0026amp; Time (Jun 13 19:28) Date and time the file/directory was last modified. 7. Name (scripts) Name of the file or directory. How to Change Permissions 1. Changing Ownership (both owner \u0026amp; group) chown ownerName fileName We can use the command named chown to change just the owner of the the file/directory.\niamyaash@fedora:~/Projects/gh/iamyaash/spells$ sudo chown itsyaash hugo.yaml iamyaash@fedora:~/Projects/gh/iamyaash/spells$ ll total 4 drwxr-xr-x. 1 iamyaash iamyaash 20 Jun 12 20:57 archetypes drwxr-xr-x. 1 iamyaash iamyaash 28 Jun 12 20:57 content -rw-r--r--. 1 itsyaash iamyaash 881 Jun 12 20:57 hugo.yaml drwxr-xr-x. 1 iamyaash iamyaash 178 Jun 12 20:57 public drwxr-xr-x. 1 iamyaash iamyaash 56 Jun 13 19:28 scripts drwxr-xr-x. 1 iamyaash iamyaash 16 Jun 12 20:57 themes Here the hugo.yaml file\u0026rsquo;s owner has been changed from iamyaash to itsyaash.\nchown ownerName:groupName fileName Changing the group name is the same as changing the owner. But, a little different while executing the command.\niamyaash@fedora:~/Projects/gh/iamyaash/spells$ sudo chown iamyaash:wheel hugo.yaml [sudo] password for iamyaash: iamyaash@fedora:~/Projects/gh/iamyaash/spells$ ll total 4 drwxr-xr-x. 1 iamyaash iamyaash 20 Jun 12 20:57 archetypes drwxr-xr-x. 1 iamyaash iamyaash 28 Jun 12 20:57 content -rw-r--r--. 1 iamyaash wheel 881 Jun 12 20:57 hugo.yaml drwxr-xr-x. 1 iamyaash iamyaash 178 Jun 12 20:57 public drwxr-xr-x. 1 iamyaash iamyaash 56 Jun 13 19:28 scripts drwxr-xr-x. 1 iamyaash iamyaash 16 Jun 12 20:57 themes Here, the group name is changed, while it\u0026rsquo;s possible change both the owner \u0026amp; group at the same time.\nAlternate: Use chgrp to change the group of the current file/directory:\nsudo chgrp groupName fileName 2. Change Mode (chmod) Linux Scoring System Permissions Score 1. Read(r) 4 2. Write(w) 2 3. Execute(x) 1 File Permission in Linux Scoring System File Permissions First 3 Next 3 Last 3 -rw-rw-r-- -rw- rw- r-- 6(4w+2r) 6(4w+2r) 4(4r) Example: iamyaash@fedora:~/Projects/gh/iamyaash/spells$ ll total 1 -rw-r--r--. 1 iamyaash iamyaash 881 Jun 12 20:57 hugo.yaml iamyaash@fedora:~/Projects/gh/iamyaash/spells$ sudo chmod 755 hugo.yaml iamyaash@fedora:~/Projects/gh/iamyaash/spells$ ll total 1 -rwxr-xr-x. 1 iamyaash iamyaash 881 Jun 12 20:57 hugo.yaml Common Permissions 644 - File Baseline (default permission given to a file) 755 - Directory Baseline (default permission given to a directory) 400 - Key Pair (locking down a file/dir to only the owner, eg:aws configs) List of Commands # change owner sudo chown iamyaash fileName.ext # change group sudo chown iamyaash:wheel fileName.ext # change file permission mode sudo chmod 644 fileName.ext #file sudo chmod 755 dirName #directory sudo chmod 400 fileName #important configs ","permalink":"https://docs.ayshell.dev/posts/linux/file-permissions/","summary":"How to manage file permissions and ownership in Linux based operating systems.","title":"Linux: Fundamentals Of File Permissions And Ownership"},{"content":"What is a user \u0026amp; group in Linux? In Linux, the terms user \u0026amp; group refer to system identities and how access is managed. A user represents an individual identity, while a group defines a collection of users who share the same access rights. Ultimately, access control in Linux revolves around these two concepts, who is accessing (user) and what permissions they have through the group that they are associated with (group).\nA Linux system without proper user and group management would be insecure, allowing anyone to access any data they want.\nUser A user is an individual account on the system. Each user has:\nA username A password Their own home directory (/home/\u0026lt;username\u0026gt;) Their own set of permissions Every time someone logs into the system, they do so as a \u0026ldquo;user\u0026rdquo;.\nGroup A group is a collection of users. Instead of assigning permission to each other individually, Linux allows permissions to be assigned to a group. All users in a group inherit the group\u0026rsquo;s permissions.\nHow Permissions Work? Every file and directory in Linux has three types of access control:\nOwner (user) Group (group) Others Each of these can be given different permission levels:\nRead(r) - View the Contents Write (w) - Modify the Contens Execute (x) - Run/Execute the File (script/program) Let take a look at a good example of how it\u0026rsquo;s going to look like on a file:\ntotal 4 drwxr-xr-x. 1 iamyaash iamyaash 20 Jun 12 23:09 archetypes -rw-r--r--. 1 iamyaash iamyaash 596 Jun 15 14:40 config.yaml drwxr-xr-x. 1 iamyaash iamyaash 28 Jun 12 23:09 content drwxr-xr-x. 1 iamyaash iamyaash 180 Jun 12 23:09 public drwxr-xr-x. 1 iamyaash iamyaash 56 Jun 13 19:28 scripts drwxr-xr-x. 1 iamyaash iamyaash 16 Jun 12 23:09 themes drwxr-xr-x - Means the owner has full access (iamyaash) group has execute \u0026amp; read access others have execute access. rw-r-r - Means the owner has read \u0026amp; write access group and others only have read access iamyaash is the owner. iamyaash is the group (same name as the user, nvm :P) How to Manage user \u0026amp; group? Let\u0026rsquo;s learn how to manage both user \u0026amp; group using hands-on excercize to help understand and practice how users and groups work in Linux.\n1. View Current User Information whoami id grep \u0026lt;username\u0026gt; /etc/passwd #used to verify whether the user is created groups #display groups associated with the current user groups \u0026lt;username\u0026gt; #display groups associated with the specified username id -Gn #same as the above id -g -n #this shows only your primary (current) group name. whoami displays the current username id display the group IDs which the current user is part of. 2. Create a New User sudo useradd newUser sudo passwd newUser useradd create a user named \u0026ldquo;newUser\u0026rdquo; passwd to set password for the user \u0026ldquo;newUser\u0026rdquo; 3. Create a New Group sudo groupadd devGroup create a group named devGroup 4. Add a User to a Group sudo usermod -aG devGroup newUser Add newUser (user) to devGroup (group) a \u0026ldquo;a\u0026rdquo; stands of append used with G, it ensures the user is added to the specified group(s) without being removed from the existing groups. G specifies the supplementary group(s) which the user should be added. (you can user multiple group separated by commas) 5. Delete a User sudo userdel -r newUser Executing the command with just userdel will only delete the user but not their home directory. Executing the command with userdel -r flag will both the user and their home directory. 6. Delete a Group sudo groupdel devGroup Note: You cannot delete a group if it’s the primary group of an existing user. You must either delete the user first or change their group.\n7. Create a File and Set Group Ownership sudo su - newUser cd - touch demo.txt ls -l demo.txt In the above commands, we\u0026rsquo;re switching to newUser and creating a file with it. Listing it will show the file\u0026rsquo;s owner is newUser.\n# Output from my device iamyaash@fedora:~$ ll total 0 -rw-r--r--. 1 iamyaash iamyaash 0 Jun 15 16:07 demo.txt Let\u0026rsquo;s switch to root user and change the group permissions,\nsudo chgrp dev /home/newUser/demo.txt ls -l /home/newUser/demo.txt # Output from my device iamyaash@fedora:~$ sudo chgrp wheel demo.txt [sudo] password for iamyaash: iamyaash@fedora:~$ ll total 0 -rw-r--r--. 1 iamyaash wheel 0 Jun 15 16:07 demo.txt 8. Set Group Permissions on a File chmod 640 /home/newUser/demo.txt Let\u0026rsquo;s understand the numeric permissions notations:\n4 - r: Read 2 - w: Write 1 - x: Execute This is the permission of the current file:\n6 - user: read/write (4+2) 4 - group: read (4) 0 - others: no permission (0) 9. Test Access as Another Group Member Add yourself into customGroup (create a group for this to experiment) sudo usermod -aG customGroup newUser Update your group access or log out and log back in. newgrp customGroup Try accessing the /home/newUser/demo.txt cat /home/newUser/demo.txt Summary To sum it up, user is an individual identity in Linux with its own username \u0026amp; password and set of permissions. A group is a collection of multiple users that allows shared access to files or resources based on group permissions. They both form the Foundation of Linux\u0026rsquo;s access control system.\n","permalink":"https://docs.ayshell.dev/posts/linux/user-group/","summary":"How to manage users \u0026amp; groups on Linux based operating systems, with exercise based explanations!","title":"Linux: User \u0026 Group Management"},{"content":"Download the Latest Version of Hugo Visit https://github.com/gohugoio/hugo/releases/latest. Download the compatible version of Hugo for your operating system. Extract the downloaded archive and move the binary file into /usr/local/bin. 1. Create a Site hugo new site sitename --format yaml # replace sitename with name of your website cd sitename 2. Installing PaperMod INSTALL : Inside the folder of your Hugo site MyFreshWebsite, run:\ngit init #initialize git as well git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod git submodule update --init --recursive # needed when you reclone your repo (submodules may not get cloned automatically) 3 Configuration 3.1 Let\u0026rsquo;s Configure hugo to use PaperMod The filename hugo.yaml may vary based on the version, so make sure to rename it to hugo.yaml if you find any other names. While this might not cause any errors, it will help avoid confusion.\u0026quot;\necho \u0026#34;theme: [\u0026#34;PaperMod\u0026#34;]\u0026#34; \u0026gt;\u0026gt; hugo.yaml 3.2 Add Search Bar In hugo.yaml add:\noutputs: home: - HTML - RSS - JSON languages: en: languageName: \u0026#34;English\u0026#34; weight: 1 menu: main: - name: Search url: search/ weight: 8 - name: Tags url: tags/ weight: 10 In contents/ add:\ntouch contents/search.md echo \u0026#34;--- title: \u0026#34;Search\u0026#34; # in any language you want layout: \u0026#34;search\u0026#34; # necessary for search # url: \u0026#34;/archive\u0026#34; # description: \u0026#34;Description for Search\u0026#34; summary: \u0026#34;search\u0026#34; placeholder: \u0026#34;Abrakadabra🪄\u0026#34; --- \u0026#34; \u0026gt;\u0026gt; contents/search.md 3.2 Layout of Homepage Go to this page, choose the layout, and make the changes as mentioned.\n👉 PaperMod Layout\n4. Let\u0026rsquo;s Test \u0026amp; Deploy hugo server #i hope it turned out well :) 4.1 Create GitHub Repository Create a Repository without any templates or LICENSE in it. Goto Settings \u0026gt; Pages Change Source settings to GitHub Actions 4.2 Create a file named hugo.yaml inside .github/workflows mkdir -p .github/workflows touch .github/workflows/hugo.yaml 4.3 Configure the GitHub Workflow Note: Ensure that HUGO_VERSION in workflow matches the version used for building hugo site.\n# Sample workflow for building and deploying a Hugo site to GitHub Pages name: Deploy Hugo site to Pages on: # Runs on pushes targeting the default branch push: branches: - main # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: \u0026#34;pages\u0026#34; cancel-in-progress: false # Default to bash defaults: run: shell: bash jobs: # Build job build: runs-on: ubuntu-latest env: HUGO_VERSION: 0.147.2 steps: - name: Install Hugo CLI run: | wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \\ \u0026amp;\u0026amp; sudo dpkg -i ${{ runner.temp }}/hugo.deb - name: Install Dart Sass run: sudo snap install dart-sass - name: Checkout uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - name: Setup Pages id: pages uses: actions/configure-pages@v5 - name: Install Node.js dependencies run: \u0026#34;[[ -f package-lock.json || -f npm-shrinkwrap.json ]] \u0026amp;\u0026amp; npm ci || true\u0026#34; - name: Build with Hugo env: HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache HUGO_ENVIRONMENT: production TZ: America/Los_Angeles run: | hugo \\ --gc \\ --minify \\ --baseURL \u0026#34;${{ steps.pages.outputs.base_url }}/\u0026#34; - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: ./public # Deployment job deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 5. Deploy Hugo! hugo git add -A git commit -m \u0026#34;deploying hugo + first commit :D\u0026#34; Copy the remote url from your repository (prefer copying ssh key over https key)\ngit remote add origin https://github.com/gohugoio/hugo.git git push origin main There you go!\n","permalink":"https://docs.ayshell.dev/posts/hugo/instant-deploy-papermod/","summary":"\u003ch1 id=\"download-the-latest-version-of-hugo\"\u003eDownload the Latest Version of Hugo\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003eVisit \u003ca href=\"https://github.com/gohugoio/hugo/releases/latest\"\u003ehttps://github.com/gohugoio/hugo/releases/latest\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003eDownload the compatible version of Hugo for your operating system.\u003c/li\u003e\n\u003cli\u003eExtract the downloaded archive and move the binary file into \u003ccode\u003e/usr/local/bin\u003c/code\u003e.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch1 id=\"1-create-a-site\"\u003e1. Create a Site\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehugo new site sitename --format yaml\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# replace sitename with name of your website\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd sitename\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"2-installing-papermod\"\u003e2. Installing PaperMod\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eINSTALL\u003c/strong\u003e : Inside the folder of your Hugo site MyFreshWebsite, run:\u003c/p\u003e\u003c/blockquote\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit init \u003cspan style=\"color:#75715e\"\u003e#initialize git as well\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit submodule add --depth\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit submodule update --init --recursive \u003cspan style=\"color:#75715e\"\u003e# needed when you reclone your repo (submodules may not get cloned automatically)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"3-configuration\"\u003e3 Configuration\u003c/h1\u003e\n\u003ch3 id=\"31-lets-configure-hugo-to-use-papermod\"\u003e3.1 Let\u0026rsquo;s Configure \u003ccode\u003ehugo\u003c/code\u003e to use \u003ccode\u003ePaperMod\u003c/code\u003e\u003c/h3\u003e\n\u003cp\u003eThe filename \u003ccode\u003ehugo.yaml\u003c/code\u003e may vary based on the version, so make sure to rename it to \u003ccode\u003ehugo.yaml\u003c/code\u003e if you find any other names. While this might not cause any errors, it will help avoid confusion.\u0026quot;\u003c/p\u003e","title":"Instant Page Deploy Hugo: papermod"},{"content":"You might feel the things you are doing are just repetive and functional (but old!), after you get familiar using git regularly. You will face a situation where you need to make some specific adjustements to the commits or something similar. It is doable but more manual, you\u0026rsquo;d wish if there\u0026rsquo;s a feature that can accomplish what you want to do now.\nAmong all that you have wished, the rebase is one of them!\nWhat is rebase? From my understanding I can\u0026rsquo;t mention a specific definition for this, but let\u0026rsquo;s keep this simple and let me phrase that in my own sentence.\nIt does exactly as it sounds, because it picks the current branch(A) and places it on top of the specified branch(B).\ni.e, All the changed that were made inside the A branch will be stacked on top of the branch B.\nApart from that, we can do so many things by using rebase,\ngit pull --rebase upstream main - To pull the upstream branch to local by rebasing local branch on top of the upstream branch. (i.e, local branch changes will be stacked on top of the incoming branch) git rebase -i HEAD~8 - To make changes to commit you have made, such as squash, edit, pick\u0026hellip; Delete Selected Commit From Commit History Determine the number of commits you need to process first,\ngit log --oneline --decorate 5bb8375 (HEAD -\u0026gt; main, orign/main, orign/HEAD, restic) posts: published jrnl along with featured image ee0dcb2 (orign/restic) revamp: major changes made to title and tags were added based on the post a3efcb5 posts: added restic backup with a feature image 2ae860b update: added feature image for git usage post 1b5cef8 update: image feature image added for omv post 21aaf5a update: publishing the omv post It displays the commit in short format, and determine the amount of commit that needs to be processed.\nWe need to remove the commit and it\u0026rsquo;s changes on \u0026ldquo;a3efcb5 posts: added restic backup with a feature image\u0026rdquo; from the history. So let\u0026rsquo;s rebase only 3 three commits (top to bottom), remove the commit from the line and save the changes.\nRebase:\ngit rebase -i HEAD~3 5bb8375 posts: published jrnl along with featured image ee0dcb2 revamp: major changes made to title and tags were added based on the post - a3efcb5 posts: added restic backup with a feature image Successfully rebased and updated refs/heads/main. Make Changes Across Commits (Single/Multiple) We need to remove a directory/file from all/specific commits, and let\u0026rsquo;s remove a file named hugo.yaml.\ngit log --oneline --decorate a3efcb5 posts: added restic backup with a feature image 2ae860b update: added feature image for git usage post 1b5cef8 update: image feature image added for omv post We\u0026rsquo;ll be removing hugo.yaml from the last 2 commits.\nRebase into each commit, make changes \u0026amp; save\ngit rebase -i HEAD~3 pick a3efcb5 posts: added restic backup with a feature image - pick 2ae860b update: added feature image for git usage post - pick 1b5cef8 update: image feature image added for omv post + edit 2ae860b update: added feature image for git usage post + edit 1b5cef8 update: image feature image added for omv post Replace pick with edit to the commits you want to make changes. Save the changes after modifying it.\nStopped at 2ae860b... update: added feature image for git usage post You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue We are dropped at the commit 2ae860b (as a temporary branch). Remove the file/folder you want and git commit --amend. Continue rebasing to the next commit 1b5cef8 using git rebase --continue. Repeat this step, until you finish all the edit. Sign All Commits After a Rebase If you forgot to use the -S flag when rebasing, your commits might be unsigned. Here’s how to fix that for all your recent commits.\n1. Start an Interactive Rebase\nFirst, open an interactive rebase session for the commits you want to fix. If you have 9 commits, you might use:\ngit rebase -i HEAD~9 2. Mark Commits to Edit\nIn the editor that pops up, you’ll see a list of your commits. For each commit you want to sign, change the word pick to edit (or just e).\nFor example:\npick 2ae860b update: added feature image for git usage post edit 1b5cef8 update: image feature image added for omv post Save and close the editor.\n3. Git Will Stop After Each Commit\nFor each commit you marked as edit, Git will pause and let you make changes.\n4. Sign the Commit\nWhile Git is paused, sign the current commit:\ngit commit -S --amend --no-edit -S signs the commit with your GPG key. --amend changes the commit without creating a new one. --no-edit keeps the commit message the same[3][4]. 5. Continue to the Next Commit\nAfter signing, move to the next commit:\ngit rebase --continue Repeat steps 4 and 5 until all commits are signed.\n6. Check Your Work\nWhen you’re done, check that all your commits are now signed:\ngit log --show-signature 7. Push Your Changes (If Needed)\nIf you already pushed your commits to a remote repository, you’ll need to force push:\ngit push --force-with-lease Summary Table Step Command/Description 1. Rebase git rebase -i HEAD~9 2. Mark as edit Change pick to edit on desired commits 3. Git pauses — 4. Sign commit git commit -S --amend --no-edit 5. Continue git rebase --continue 6. Check git log --show-signature 7. Push git push --force-with-lease ","permalink":"https://docs.ayshell.dev/posts/git/rebasing-tips/","summary":"Introduction into the git rebase feature, explains how to make changes to branches and commits","title":"Git Basics: Rebase"},{"content":"Let\u0026rsquo;s move into the / (root) direcory: iamyaash@fedora:/$ ll total 20 dr-xr-xr-x. 1 root root 0 Jul 17 2024 afs lrwxrwxrwx. 1 root root 7 Jul 17 2024 bin -\u0026gt; usr/bin dr-xr-xr-x. 6 root root 4096 Mar 26 02:33 boot drwxr-xr-x. 21 root root 4400 Mar 30 14:23 dev drwxr-xr-x. 1 root root 4870 Mar 28 21:04 etc drwxr-xr-x. 1 root root 16 Feb 23 23:19 home lrwxrwxrwx. 1 root root 7 Jul 17 2024 lib -\u0026gt; usr/lib lrwxrwxrwx. 1 root root 9 Jul 17 2024 lib64 -\u0026gt; usr/lib64 drwx------. 1 root root 0 Oct 24 20:17 lost+found drwxr-xr-x. 1 root root 0 Jul 17 2024 media drwxr-xr-x. 1 root root 0 Jul 17 2024 mnt drwxr-xr-x. 1 root root 48 Feb 23 18:34 opt dr-xr-xr-x. 576 root root 0 Mar 30 2025 proc dr-xr-x---. 1 root root 168 Mar 19 13:11 root drwxr-xr-x. 58 root root 1500 Mar 30 17:30 run lrwxrwxrwx. 1 root root 8 Jul 17 2024 sbin -\u0026gt; usr/sbin drwxr-xr-x. 1 root root 0 Jul 17 2024 srv dr-xr-xr-x. 13 root root 0 Mar 30 14:22 sys drwxrwxrwt. 28 root root 720 Mar 30 19:43 tmp drwxr-xr-x. 1 root root 168 Oct 24 20:19 usr drwxr-xr-x. 1 root root 200 Oct 24 20:27 var Directory Description /bin Contains essential binaries (e.g., ls, pwd, cat, vim) that can be accessed by all users. These are required for system operation. /sbin Stores system binaries (e.g., mount, adduser, deluser) that can only be executed by root or with sudo. /lib Contains shared libraries required by /bin and /sbin. Often a symbolic link to /usr/lib. /usr Holds user-related programs and utilities. /usr/bin Contains non-essential binaries for user applications (e.g., nano, vim, gcc, dnf). /usr/local/bin Stores user-installed binaries to avoid conflicts with system package manager installations. $PATH Environment variable that defines directories where executables are searched when running commands. /etc Stores system-wide configuration files (e.g., /etc/resolv.conf, /etc/hostname). Most are editable text files ending in .conf. /home Contains personal files, settings, and user-specific directories (/home/username). /boot Contains files required for booting the system, including the Linux kernel. /dev Provides access to hardware devices as if they were files (e.g., /dev/sda, /dev/null). /opt Stores optional or third-party software packages that are not part of the default system. /var Contains variable data such as logs (/var/log), spool files, and caches. /tmp Stores temporary files that are deleted on reboot. /proc Virtual directory containing real-time system information, such as /proc/cpuinfo (CPU details) and /proc/meminfo (memory usage). ","permalink":"https://docs.ayshell.dev/posts/linux/linux-directories/","summary":"A table summarizing Linux directories for a quick reference.","title":"Linux: Directories"},{"content":"Adding New ssh Key Create .ssh key: ssh-keygen -t rsa -b 4096 -C \u0026#34;email\u0026#34; Save it the keys in a specific directory location\nAdd the key to ssh agent ssh-add /home/user/.ssh/ssh-filename Verify the key has been added ssh-add -l Output:\nGenerating public/private rsa key pair. Enter file in which to save the key (/home/username/.ssh/id_rsa): /home/username/.ssh/temp Enter passphrase for \u0026#34;/home/username/.ssh/temp\u0026#34; (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/username/.ssh/temp Your public key has been saved in /home/username/.ssh/temp.pub The key fingerprint is: SHA256:zUJ0dU9gncA7rVf6+C5BsMmBVdHmCMUqzkEGWpu6QWM temp@gmail.com The key\u0026#39;s randomart image is: +---[RSA 4096]----+ | +..++=O=o| | + ++ ++.++| | E +o . Bo+.| | o + oo =oo.o| | o Sooo .o..| | o .o .o. | | . .+ | | o .| | +o| +----[SHA256]-----+\u0026#39; username@fedora:~$ ssh-add /home/username/.ssh/temp Identity added: /home/username/.ssh/temp (temp@gmail.com) username@fedora:~$ ssh-add -l 4096 SHA256:\u0026lt;keys\u0026gt; \u0026lt;email\u0026gt; (RSA) 4096 SHA256:\u0026lt;keys\u0026gt; \u0026lt;email\u0026gt; (RSA) 3072 SHA256:\u0026lt;keys\u0026gt; \u0026lt;email\u0026gt; (RSA) 4096 SHA256:\u0026lt;keys\u0026gt; \u0026lt;email\u0026gt; (RSA) ","permalink":"https://docs.ayshell.dev/posts/ssh/ssh/","summary":"\u003ch2 id=\"adding--new-ssh-key\"\u003eAdding  New \u003ccode\u003essh\u003c/code\u003e Key\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eCreate \u003ccode\u003e.ssh\u003c/code\u003e key:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh-keygen -t rsa -b \u003cspan style=\"color:#ae81ff\"\u003e4096\u003c/span\u003e -C \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cblockquote\u003e\n\u003cp\u003eSave it the keys in a specific directory location\u003c/p\u003e\u003c/blockquote\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003eAdd the key to \u003ccode\u003essh\u003c/code\u003e agent\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh-add /home/user/.ssh/ssh-filename\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col start=\"3\"\u003e\n\u003cli\u003eVerify the key has been added\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh-add -l\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eOutput:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGenerating public/private rsa key pair.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eEnter file in which to save the key \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e/home/username/.ssh/id_rsa\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: /home/username/.ssh/temp   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eEnter passphrase \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/home/username/.ssh/temp\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eempty \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e no passphrase\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eEnter same passphrase again: \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eYour identification has been saved in /home/username/.ssh/temp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eYour public key has been saved in /home/username/.ssh/temp.pub\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eThe key fingerprint is:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSHA256:zUJ0dU9gncA7rVf6+C5BsMmBVdHmCMUqzkEGWpu6QWM temp@gmail.com\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eThe key\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;s randomart image is:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e+---[RSA 4096]----+\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|        +..++=O=o|\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|       + ++ ++.++|\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|      E +o . Bo+.|\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|     o + oo =oo.o|\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|      o Sooo .o..|\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|       o .o  .o. |\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|      .       .+ |\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|              o .|\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e|               +o|\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e+----[SHA256]-----+\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusername@fedora:~$ ssh-add /home/username/.ssh/temp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eIdentity added: /home/username/.ssh/temp \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003etemp@gmail.com\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eusername@fedora:~$ ssh-add -l\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e4096\u003c/span\u003e SHA256:\u0026lt;keys\u0026gt; \u0026lt;email\u0026gt; \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eRSA\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e4096\u003c/span\u003e SHA256:\u0026lt;keys\u0026gt; \u0026lt;email\u0026gt; \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eRSA\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e3072\u003c/span\u003e SHA256:\u0026lt;keys\u0026gt; \u0026lt;email\u0026gt; \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eRSA\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e4096\u003c/span\u003e SHA256:\u0026lt;keys\u0026gt; \u0026lt;email\u0026gt; \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eRSA\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":" Generate SSH Keys"},{"content":"Setting up git in your device git config --global user.name \u0026lt;your-username\u0026gt; git config --global user.email \u0026lt;your-email\u0026gt; git config --global user.signingKey \u0026lt;keyID\u0026gt; --global: The configuration applies to all repositories for the current user. --local: The configuration applies only to the current repository. --system: The configuration applies to all users on the system. user.name \u0026amp; user.email define the author\u0026rsquo;s identity for commits. user.signingKey specifies the GPG key ID used for signing commits and tags. To display all the current configurations:\ngit config --list To display the specific configurations:\ngit config --global user.name git config --global user.email Enable commit signing: git config --global commit.gpgSign true After enabling this, every commit will be automatically signed without needing the -S flag.\nDisable commit signing: git config --global --unset commit.gpgSign General Use Cases: Staging the changes: git add filename.ext -A will select all the changes in the current directory. (Not a good practice, unless you know what you are doing) -i for interactive picking the changes. (Useful for handling large changes) Committing the changes: git commit -S -am \u0026#34;commit message\u0026#34; -S - Signs the commit with your GPG key. -a - Stages all modified and deleted tracked files (but not new files). -m - Allows entering the commit message inline. Pushing the Changes: git push \u0026lt;remote\u0026gt; \u0026lt;branch\u0026gt; \u0026lt;remote\u0026gt; - The name of the remote repository (e.g., origin). # find the remote repository name by git remote -v \u0026lt;branch\u0026gt; - The name of the branch to push (e.g., main or feature-branch). # find the available or current branch by git branch Show the commits: git log --oneline --decorate --graph --oneline - shows the commit in single line without any verbose output. --decorate - use pretty printing (with colors!) --graph - displays the commit messages in graph format. (easily understandable) ","permalink":"https://docs.ayshell.dev/posts/git/howtousegit/","summary":"A quick reference guide to the most essential Git commands for everyday use, including initializing repositories, making commits, branching, and working with remotes.","title":"Git Basics: Essential Commands"},{"content":"I noticed that I\u0026rsquo;m keep deploying many pages on Github and still looking at the documentation. So I decided to make a short documentation how to do it fast (keeping me from looking at the documentation)\nCreate a hugo site in a specific directory you want: hugo new site sitename Replace the sitename with the actual sitename you want to create.\nHead inside the directory(hugo site) cd sitename git init Download a theme (we\u0026rsquo;re using holy theme here) git submodule add https://github.com/serkodev/holy.git themes/holy echo \u0026#34;theme = \u0026#39;holy\u0026#39;\u0026#34; \u0026gt;\u0026gt; hugo.toml Let\u0026rsquo;s test it locally! hugo server Create a GitHub Repository Head inside the Repository on GitHub Goto Settings \u0026gt; Pages Change the Source settings to \u0026ldquo;GitHub Actions\u0026rdquo; Create a file named hugo.yaml inside .github/workflows mkdir -p .github/workflows touch .github/workflows/hugo.yaml Copy and paste the text into YAML file # Sample workflow for building and deploying a Hugo site to GitHub Pages name: Deploy Hugo site to Pages on: # Runs on pushes targeting the default branch push: branches: - main # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: \u0026#34;pages\u0026#34; cancel-in-progress: false # Default to bash defaults: run: shell: bash jobs: # Build job build: runs-on: ubuntu-latest env: HUGO_VERSION: 0.144.2 steps: - name: Install Hugo CLI run: | wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \\ \u0026amp;\u0026amp; sudo dpkg -i ${{ runner.temp }}/hugo.deb - name: Install Dart Sass run: sudo snap install dart-sass - name: Checkout uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - name: Setup Pages id: pages uses: actions/configure-pages@v5 - name: Install Node.js dependencies run: \u0026#34;[[ -f package-lock.json || -f npm-shrinkwrap.json ]] \u0026amp;\u0026amp; npm ci || true\u0026#34; - name: Build with Hugo env: HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache HUGO_ENVIRONMENT: production TZ: America/Los_Angeles run: | hugo \\ --gc \\ --minify \\ --baseURL \u0026#34;${{ steps.pages.outputs.base_url }}/\u0026#34; - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: ./public # Deployment job deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 Head inside the root directory of your sitename hugo git add -A git commit -m \u0026#34;deploying the sitename\u0026#34; git push origin main ","permalink":"https://docs.ayshell.dev/posts/hugo/instant-deploy-holy/","summary":"\u003cp\u003eI noticed that I\u0026rsquo;m keep deploying many pages on Github and still looking at the documentation. So I decided to make a short documentation how to do it fast (keeping me from looking at the documentation)\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eCreate a \u003ccode\u003ehugo\u003c/code\u003e site in a specific directory you want\u003c/strong\u003e:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehugo new site sitename\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cblockquote\u003e\n\u003cp\u003eReplace the \u003ccode\u003esitename\u003c/code\u003e with the actual sitename you want to create.\u003c/p\u003e\u003c/blockquote\u003e\n\u003cul\u003e\n\u003cli\u003eHead inside the directory(\u003cem\u003e\u003ccode\u003ehugo site\u003c/code\u003e\u003c/em\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd sitename\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit init\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003eDownload a theme (\u003cem\u003ewe\u0026rsquo;re using \u003ccode\u003eholy\u003c/code\u003e theme here\u003c/em\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit submodule add https://github.com/serkodev/holy.git themes/holy\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;theme = \u0026#39;holy\u0026#39;\u0026#34;\u003c/span\u003e \u0026gt;\u0026gt; hugo.toml\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003eLet\u0026rsquo;s test it locally!\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehugo server\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col start=\"2\"\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/new\"\u003e\u003cstrong\u003eCreate a GitHub Repository\u003c/strong\u003e\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHead inside the Repository on GitHub\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eGoto \u003ccode\u003eSettings \u0026gt; Pages\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eChange the \u003cem\u003e\u003ccode\u003eSource\u003c/code\u003e\u003c/em\u003e settings to \u0026ldquo;\u003cstrong\u003e\u003ccode\u003eGitHub Actions\u003c/code\u003e\u003c/strong\u003e\u0026rdquo;\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eCreate a file named \u003ccode\u003ehugo.yaml\u003c/code\u003e inside \u003ccode\u003e.github/workflows\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir -p .github/workflows\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etouch .github/workflows/hugo.yaml\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col start=\"5\"\u003e\n\u003cli\u003eCopy and paste the text into \u003ccode\u003eYAML\u003c/code\u003e file\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yml\" data-lang=\"yml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Sample workflow for building and deploying a Hugo site to GitHub Pages\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eDeploy Hugo site to Pages\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eon\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e# Runs on pushes targeting the default branch\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003epush\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ebranches\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#ae81ff\"\u003emain\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e# Allows you to run this workflow manually from the Actions tab\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eworkflow_dispatch\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003epermissions\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003econtents\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eread\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003epages\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ewrite\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eid-token\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ewrite\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003econcurrency\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003egroup\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;pages\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ecancel-in-progress\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Default to bash\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003edefaults\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003erun\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eshell\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ebash\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ejobs\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e# Build job\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ebuild\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eruns-on\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eubuntu-latest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eenv\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eHUGO_VERSION\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e0.144.2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eInstall Hugo CLI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003erun\u003c/span\u003e: |\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e          wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e          \u0026amp;\u0026amp; sudo dpkg -i ${{ runner.temp }}/hugo.deb\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eInstall Dart Sass\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003erun\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003esudo snap install dart-sass\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eCheckout\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003euses\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eactions/checkout@v4\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003ewith\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003esubmodules\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003erecursive\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003efetch-depth\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eSetup Pages\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003eid\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003epages\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003euses\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eactions/configure-pages@v5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eInstall Node.js dependencies\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003erun\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;[[ -f package-lock.json || -f npm-shrinkwrap.json ]] \u0026amp;\u0026amp; npm ci || true\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eBuild with Hugo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003eenv\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eHUGO_CACHEDIR\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${{ runner.temp }}/hugo_cache\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eHUGO_ENVIRONMENT\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eproduction\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eTZ\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eAmerica/Los_Angeles\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003erun\u003c/span\u003e: |\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e          hugo \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e            --gc \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e            --minify \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e            --baseURL \u0026#34;${{ steps.pages.outputs.base_url }}/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eUpload artifact\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003euses\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eactions/upload-pages-artifact@v3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003ewith\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003epath\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e./public\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e# Deployment job\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edeploy\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eenvironment\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003egithub-pages\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eurl\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${{ steps.deployment.outputs.page_url }}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eruns-on\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eubuntu-latest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eneeds\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ebuild\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esteps\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eDeploy to GitHub Pages\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003eid\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003edeployment\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003euses\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eactions/deploy-pages@v4\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col start=\"6\"\u003e\n\u003cli\u003eHead inside the root directory of your \u003ccode\u003esitename\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehugo\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit add -A\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit commit -m \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;deploying the sitename\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit push origin main\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Instant Page Deploy Hugo: holy"},{"content":"What is nmcli? The nmcli means NetworkManager Command Line Interface. It\u0026rsquo;s command-line utility tool used for controlling NetworkManager and reporting network status.\nIn simple terms, we use that to interact with network related devices.\nHow to use it? I don\u0026rsquo;t have proper way to explain, but let\u0026rsquo;s learn it with a case-scenario:\nConnect to a wifi network: Turn on the wifi module: sudo nmcli radio wifi on List the available networks: sudo nmcli device wifi list In case, it didn\u0026rsquo;t display any network, please rescan the available network and list it:\nsudo nmcli device wifi rescan sudo nmcli device wifi list Let\u0026rsquo;s connect to the device: Let\u0026rsquo;s take an example and connect to that device IN-USE BSSID SSID MODE CHAN RATE SIGNAL BARS SECURITY * C8:D7:79:A6:28:24 JioFi2_A62824 Infra 7 130 Mbit/s 86 ▂▄▆█ WPA2 sudo nmcli device wifi connect JioFi2_A62824 password \u0026#34;enter your password here inside dquotes\u0026#34; Modify the DNS Address of the Network List the available networks sudo nmcli connection show This will show the available networks connected to your device. Output:\nNAME UUID TYPE DEVICE Wired connection 1 82aadf2b-xxxx-xxxx-a3ec-xxxxxxxxxxxx ethernet enp2s0 lo e6b49b80-xxxx-xxxx-b8d7-xxxxxxxxxxxx loopback lo docker0 bfcf407f-xxxx-xxxx-bbfe-xxxxxxxxxxxx bridge docker0 Modify the Wired connection 1 network: sudo nmcli connection modify \u0026#34;Wired connection 1\u0026#34; ipv4.addresses 192.168.31.xx/24 ipv4.gateway 192.168.31.1 ipv4.dns \u0026#34;8.8.8.8 8.8.4.4\u0026#34; ipv4.method manual ipv4.addresses 192.168.31.xx/24 - defines the custom address we want to assign to the network. ipv4.gateway 192.168.31.1 - defines the default address of the router\u0026rsquo;s IP address. ipv4.dns \u0026quot;8.8.8.8 8.8.4.4\u0026quot; - Assigning the custom DNS addresses ipv4.method manual - Setting the method of IPV4 DNS address assinging manually. Restart the Connection Restart the connection after modifying it to apply the changes: sudo nmcli connection down \u0026#34;Wired connection 1\u0026#34; sudo nmcli connection up \u0026#34;Wired connection 1\u0026#34;` Verify the New IP Address Check if the IP has been assigned successfully: ip addr show wlan0 | grep inet Output: (Shows something like this)\ndocker0: \u0026lt;NO-CARRIER,BROADCAST,MULTICAST,UP\u0026gt; mtu 1500 qdisc noqueue state DOWN group default link/ether 2a:fa:ba:87:b2:82 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever Disabling IPv6 If you don\u0026rsquo;t need IPv6, you can disable it for the specified connection:\nsudo nmcli connection modify \u0026lt;connection-name\u0026gt; ipv6.method ignore Modify the Name of the Network sudo nmcli connection modify \u0026lt;connection-name\u0026gt; connection.id \u0026lt;new-connection-name\u0026gt; connection.id - Responsible for changing the name of the connection. Troubleshoot (Reset to Original State) If you ever messed up modifying the connections manually, you can simply revert back to default state which will solve the errors.\nWhen the changes go wrong, it will raise conflicts between systemd-resolved \u0026amp; NetworkManager. At first, let\u0026rsquo;s disable \u0026amp; stop the systemd-resolved. sudo systemctl stop systemd-resolved sudo systemctl disable systemd-resolved Reset the resolv.conf and create a symlink as well.\nsudo rm /etc/resolv.conf sudo ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf Note: The symlink to stub-resolv.conf ensures system-default DNS resolution.\nNow that it resets, we can restart the DNS services which is managed is by NetworkManager. sudo systemctl enable systemd-resolved sudo systemctl start systemd-resolved sudo sytemctl restart NetworkManager Verify the DNS configuration using resolvectl resolvectl status This will display the logs and status of the Network.\nCheck whether the configuration is reflected in resolv.conf cat /etc/resolv.conf Summary: Basically, we first stop the services that manages the DNS, delete the file (resolv.conf) that holds the information for the DNS addresses and create the same file by symbolically linking it with /run/systemd/resolve/stub-resolv.conf (that\u0026rsquo;s how it usually originated from anyway). Then we restart the services once again from the beginning which will reads the file and writes the default address based what is being written in the connection\u0026rsquo;s configs.\n","permalink":"https://docs.ayshell.dev/posts/nmcli/nmcli/","summary":"\u003ch1 id=\"what-is-nmcli\"\u003eWhat is \u003ccode\u003enmcli\u003c/code\u003e?\u003c/h1\u003e\n\u003cp\u003eThe \u003ccode\u003enmcli\u003c/code\u003e means \u003cstrong\u003eNetworkManager Command Line Interface\u003c/strong\u003e. It\u0026rsquo;s command-line utility tool used for controlling \u003ccode\u003eNetworkManager\u003c/code\u003e and reporting network status.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eIn simple terms, we use that to interact with network related devices.\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"how-to-use-it\"\u003eHow to use it?\u003c/h2\u003e\n\u003cp\u003eI don\u0026rsquo;t have proper way to explain, but let\u0026rsquo;s learn it with a case-scenario:\u003c/p\u003e\n\u003ch3 id=\"connect-to-a-wifi-network\"\u003eConnect to a wifi network:\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eTurn on the \u003ccode\u003ewifi\u003c/code\u003e module:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nmcli radio wifi on\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col start=\"2\"\u003e\n\u003cli\u003eList the available networks:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nmcli device wifi list\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIn case, it didn\u0026rsquo;t display any network, please \u003ccode\u003erescan\u003c/code\u003e the available network and list it:\u003c/p\u003e","title":"Getting Started with nmcli (NetworkManager CLI)"},{"content":" Note: Make sure to Disable Secure Boot, else whatever you do it won\u0026rsquo;t work :)\nInstall \u0026amp; Switch 1. Install the required dependencies\nsudo dnf install akmod-nvidia xorg-x11-drv-nvidia xorg-x11-drv-nvidia-cuda 2. Edit the environment configuration file for your shell\nsudo nano /etc/environment 3. Add the following lines to enable the GPU\n__GLX_VENDOR_LIBRARY_NAME=nvidia __NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only 4. Restart the system\nsudo reboot Download and execute this script to automate the above process!\n5. Check the status of the currently selected GPU\nglxinfo | grep \u0026#34;OpenGL renderer\u0026#34; thisisyaash@yaashs-fedora:~$ glxinfo | grep \u0026#34;OpenGL renderer\u0026#34; OpenGL renderer string: NVIDIA GeForce RTX 3050 Laptop GPU/PCIe/SSE2 It will show the result something like this with the respective gpu information\nIf the above steps didn\u0026rsquo;t worked, then follow the below steps :) 1. Veriify the NVIDIA Kernel Module:\nlsmod | grep nvidia If no output then it\u0026rsquo;s not loaded, else Good!\n2. Reinstall the NVIDIA drivers\ncheck whether the NVIDIA driver is connected /sbin/lspci | grep -e VGA remove existing drivers sudo dnf remove *nvidia* reinstall the NVIDIA driver sudo dnf install akmod-nvidia xorg-x11-drv-nvidia xorg-x11-drv-nvidia-cuda rebuild the kernel sudo akmods --force ensure the NVIDIA modules are loaded sudo modprobe nvidia lsmod | grep nvidia reboot sudo reboot ","permalink":"https://docs.ayshell.dev/posts/nvidia/switch-nvidia/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003ccode\u003eNote\u003c/code\u003e: Make sure to \u003cstrong\u003eDisable Secure Boot\u003c/strong\u003e, else whatever you do it won\u0026rsquo;t work :)\u003c/p\u003e\u003c/blockquote\u003e\n\u003ch1 id=\"install--switch\"\u003eInstall \u0026amp; Switch\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003e1. Install the required dependencies\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo dnf install akmod-nvidia xorg-x11-drv-nvidia xorg-x11-drv-nvidia-cuda\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e2. Edit the environment configuration file for your shell\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nano /etc/environment\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e3. Add the following lines to enable the GPU\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e__GLX_VENDOR_LIBRARY_NAME\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003envidia\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e__NV_PRIME_RENDER_OFFLOAD\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e__VK_LAYER_NV_optimus\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eNVIDIA_only\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e4. Restart the system\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo reboot\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ca href=\"https://github.com/iamyaash/spells/blob/main/content/posts/nvidia/install_nvidia.sh\"\u003eDownload\u003c/a\u003e and execute this script to automate the above process!\u003c/p\u003e","title":"Switch to NVIDIA GPU on Fedora Linux"}]