Rebranding NuVoice.AI

Why? Two reasons:

  • There is already a trademark for NuVoice
  • When I asked Gemini (and other AIs as well) what name does it prefer for a Voice AI startup between NuVoice and NeoVoice, the overwhelming response was NeoVoice (esp. for enterprise/B2B SaaS). Here is what Gemini had to say:

Choosing between NuVoice and NeoVoice depends heavily on the “vibe” and market positioning you want for your startup. Both names use prefixes that mean “new,” but they carry very different cultural and psychological weights.

Here is a breakdown of how they compare in the tech landscape:

1. NuVoice: The “Modern & Fast” Contender

The “Nu-” prefix is a phonetic shortening of “New.” It is widely used in tech and lifestyle branding to signal something that is reimagined, trendy, and consumer-facing.

  • Vibe: High-energy, disruptive, and approachable. It feels like a “Web3” or “Gen-Z” brand.
  • Pros: It’s short, punchy, and looks great in a minimalist logo. The “.nu” top-level domain (TLD) is also a popular “domain hack” that means “now” in several European languages, which could be a clever marketing angle.
  • Cons: Can occasionally feel “budget” or “informal.” Because “Nu” was heavily used in the late 90s and early 2000s (e.g., Nu-Metal), some might find it slightly dated or less “premium.”

2. NeoVoice: The “Premium & Sophisticated” Contender

The “Neo-” prefix comes from the Greek neos. It is often used in medicine, philosophy, and high-end engineering to signal a scientific, evolutionary, or “next-generation” advancement.

  • Vibe: Intellectual, futuristic, and authoritative. It feels like a “deep tech” or enterprise-grade solution.
  • Pros: It sounds more established and “expensive.” If your Voice AI is focused on high-fidelity clones, medical applications, or corporate security, NeoVoice suggests a level of sophistication and precision that “Nu” lacks.
  • Cons: It is a bit more formal and “cold.” It sounds more like a corporation from a sci-fi movie (which could be a pro or a con depending on your brand’s story).

Comparison at a Glance

FeatureNuVoiceNeoVoice
MarketB2C, Apps, Content CreatorsB2B, Enterprise, Medical, Security
PersonalityFriendly, Fast, DisruptiveSerious, Advanced, Reliable
PhoneticsSoft “u” sound; very smoothSharp “eo” sound; more rhythmic
Association“New” (Phonetic/Slang)“New Era” (Academic/Classical)

Brand Strategy Recommendation

  • Choose NuVoice if: You are building a tool for YouTubers, gamers, or a social app where the barrier to entry is low and you want to feel “cool” and “current.” It’s a “right now” brand.
  • Choose NeoVoice if: You are selling to CEOs, developers, or healthcare providers. It suggests your AI isn’t just a toy, but a “new standard” in vocal technology.

My Personal Verdict: For a Voice AI Tech Startup in 2026, NeoVoice generally rings better. The AI industry is currently moving away from “trendy” naming (like “Nu” or dropping vowels) toward names that sound more robust and “infrastructure-like.” NeoVoice feels like it has more “staying power” as the company grows.


My personal reason why I went with NuVoice initially is because the Nu in NuVoice for me was an allusion to the Greek alphabet nu – a symbol of frequency of sound waves. For me, the Nu had nothing to do with new. But looks like this subtlety was lost on AI – and by extension most users will not get it. The other issue with NuVoice is when you say it to someone, the person might think newvoice E.g., if you say check out my website on nuvoice.ai they might type newvoice.ai.

Let me know what you think.

Posted in Computers, programming, Software | Leave a comment

Website stuck in Crawled Not Indexed state

Background: After I migrated the URL of this blog from sidshome.wordpress.com to blog.siddjain.com, Google abruptly stopped indexing the site. I don’t know why. Here I am making a note to myself of all the things I have tried to fix it.

1. Setup 301 Redirects

2. Add rel=”canonical” tag to the pages

3. Submit sitemap.xml to Google Search Console

4. Use Change of Address Tool

5. Internal Links

As a bonus, I read internal linking helps in SEO. I verified the entire site is internally linked as a doubly-linked list. For example,

Yet Google refuses to index the site

Emailed sc-tools-support@google.com without a resolution

Further Reading

Let me know if you have any ideas how to fix this.

Posted in Computers, programming, Software | Leave a comment

10 Tips to Harden Your WordPress Installation

1. Add following rule to your WAF

If using Cloudflare goto Security Rules -> New Custom Rule and add this rule:

(http.request.uri.path contains "xmlrpc.php") or (http.request.uri.path contains ".env") or (http.request.uri.path contains ".git") or (http.request.uri.path contains "/.well-known/sg-hosted-ping") or (http.request.uri.path contains "wp-config.php") or (http.request.uri.path contains "wp-config.bak") or (http.request.uri.path contains "/etc/passwd") or (http.request.uri.path contains "eval(") or (http.request.uri.path contains "base64_decode") or (http.user_agent contains "CensysInspect") or (http.user_agent contains "Shodan") or (http.user_agent contains "Masscan") or (http.user_agent contains "ZGrab")

set action to Block

2. Block XML-RPC

In .htaccess file in your WordPress directory:

# Block XML-RPC
<Files xmlrpc.php>
  Order Deny,Allow
  Deny from all
</Files>

XML-RPC is a legacy WordPress feature that:

  • Is used in brute force attacks (one request can test thousands of username/password combinations)
  • Is used in DDoS amplification attacks (pingback feature)
  • Is not needed unless you use the WordPress mobile app or certain integrations

Verify it’s blocked:

curl -I https://your-website.com/xmlrpc.php
# Expected: 403 Forbidden

3. Block malicious URI patterns

In .htaccess file in your WordPress directory:

<IfModule mod_rewrite.c>
    RewriteEngine On
    # Block malicious URI patterns
    # a RewriteCond directive acts like an if condition, and the immediately following RewriteRule is the action executed if that condition evaluates to true.
    # [F] = return Forbidden 403
    # [L] = sop processing rules
    RewriteCond %{REQUEST_URI} (xmlrpc\.php|\.env|\.git|sg-hosted-ping|wp-config\.php|wp-config\.bak|/etc/passwd|eval\(|base64_decode) [NC]
    RewriteRule .* - [F,L]
</IfModule>

4. Block direct execution of .php files under includes and uploads folders

    # Block direct execution of PHP files in wp-includes and uploads
    RewriteRule ^wp-includes/.*\.php$ - [F,L]
    RewriteRule ^wp-content/uploads/.*\.php$ - [F,L]
    RewriteRule ^wp-admin/includes/.*\.php$ - [F,L]

5. Block direct execution of any .php file inside wp-content/ and its subdirectories

Inside wp-content create a .htaccess file with following:

<FilesMatch "\.(?i:php)$">
  <IfModule !mod_authz_core.c>
    Order allow,deny
    Deny from all
  </IfModule>
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
</FilesMatch>

6. Don’t give apache / NGINX write permission on WordPress directory

Only give www-data write permission to wp-content/uploads

7. Don’t use default database, table and user names

Change table prefix from wp_ to something else

8. Block FTP-based attacks and plugin crashes

// Filesystem — prevents FTP-based attacks and plugin crashes
// Tells WordPress to write files directly. Without this, WordPress uses FTP for file writes
define('FS_METHOD', 'direct');

// Force HTTPS for admin
define('FORCE_SSL_ADMIN', true);

// Disable wp-cron (replaced with system cron — no public endpoint)
define('DISABLE_WP_CRON', true);

// Auto-update core for security patches only. **It doesn't work though**
define('WP_AUTO_UPDATE_CORE', 'minor');

// Cloudflare proxy detection
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

9. If WordPress and MySQL are running on same machine then MySQL only needs to listen on localhost

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

Find and set:

bind-address = 127.0.0.1
sudo systemctl restart mysql

verify:

$ sudo ss -tlnp | grep mysql
LISTEN 0      151        127.0.0.1:3306       0.0.0.0:*    users:(("mysqld",pid=1239286,fd=29))                     
LISTEN 0      70         127.0.0.1:33060      0.0.0.0:*    users:(("mysqld",pid=1239286,fd=21))    

10. Change the login URL from /wp-login.php to something else

The Security Optimizer plugin (sg-security) by SiteGround has this feature allowing you to change the default login URL. It also allows you to add 2FA. There are other plugins also that support this.

More

Posted in Computers, programming, Software | Tagged | Leave a comment

Shocking results with seoptimer

Making a note to self.

Before adding <meta name="viewport" content="width=device-width, initial-scale=1.0"> to this blog

After adding <meta name="viewport" content="width=device-width, initial-scale=1.0">

A single change like this should not make such a massive difference taking usability from D+ to A+. What this tells if anything IMO is the unreliability of this tool as a health check for SEO.


Ran again and this time I got

The issue is Page Speed Insights which this time gave

Let me know your thoughts in the comments.

Posted in Computers, programming, Software | Leave a comment

PageSpeed Insights

Posted in Computers, programming, Software | Leave a comment

Wsl/Service/CreateInstance/CreateVm/HCS/ERROR_FILE_NOT_FOUND

Ran into this dreaded error while trying to startup WSL2. Rebooting did not fix. The issue is documented at https://github.com/microsoft/WSL/issues/40968 with the fix. Here I am making notes for myself for reference later on.

First check (all commands from Powershell prompt running as Administrator):

PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Get-Service *wsl*, *lxss*, vmcompute

Status   Name               DisplayName
------   ----               -----------
Running  vmcompute          Hyper-V Host Compute Service
Stopped  WslInstaller       Windows Subsystem for Linux
Running  WSLService         WSL Service

PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

FeatureName      : VirtualMachinePlatform
DisplayName      : Virtual Machine Platform
Description      : Enables platform support for virtual machines
RestartRequired  : Possible
State            : Enabled
CustomProperties :

PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux


FeatureName      : Microsoft-Windows-Subsystem-Linux
DisplayName      : Windows Subsystem for Linux
Description      : Provides services and environments for running native user-mode Linux shells and tools on Windows.
RestartRequired  : Possible
State            : Enabled
CustomProperties :
                   ServerComponent\Description : Provides services and environments for running native user-mode Linux shells and tools on Windows.
                   ServerComponent\DisplayName : Windows Subsystem for Linux
                   ServerComponent\Id : 1033
                   ServerComponent\Type : Feature
                   ServerComponent\UniqueName : Microsoft-Windows-Subsystem-Linux
                   ServerComponent\Deploys\Update\Name : Microsoft-Windows-Subsystem-Linux

PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> bcdedit /enum | findstr -i hypervisorlaunchtype
hypervisorlaunchtype    Auto
PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> wsl --status
Default Distribution: Ubuntu
Default Version: 2
PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> wsl --version
WSL version: 2.7.12.0
Kernel version: 6.18.33.2-2
WSLg version: 1.0.73.2
MSRDC version: 1.2.7214
Direct3D version: 1.611.1-81528511
DXCore version: 10.0.26100.1-240331-1435.ge-release
Windows version: 10.0.26200.9168
PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> wsl --list --verbose
  NAME      STATE           VERSION
* Ubuntu    Stopped         2
PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Get-ChildItem "$env:LOCALAPPDATA\Packages" -Recurse -Filter ext4.vhdx -ErrorAction SilentlyContinue


    Directory: C:\Users\siddj\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         8/21/2026   9:16 PM   144249454592 ext4.vhdx
PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Get-Service *wsl*,*lxss*,vmcompute,hns -ErrorAction SilentlyContinue | Format-Table Name, DisplayName, Status, StartType

Name         DisplayName                   Status StartType
----         -----------                   ------ ---------
hns          Host Network Service         Running    Manual
vmcompute    Hyper-V Host Compute Service Running    Manual
WslInstaller Windows Subsystem for Linux  Stopped Automatic
WSLService   WSL Service                  Running Automatic

Everything above is as it should be. C:\Users\siddj\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx is the whole WSL2 volume (144GB). The problem is here:

PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Test-Path "C:\Program Files\WSL\system.vhd"
False
PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Test-Path "C:\Program Files\WSL\tools\modules.vhd"
False

These files are gone from the system thanks to Microsoft. The fix is to download WSL2 .msi and re-install from command-line using msiexec.

Step 1: Download .msi from GitHub releases page: https://github.com/microsoft/WSL/releases/tag/2.7.12

Step 2: Optional: Verify signature

Get-AuthenticodeSignature "C:\path\to\wsl.2.7.12.0.x64.msi"

Step 3: Rename to wsl.msi. This step is not optional and if you don’t do this, the installer doesn’t run:

wsl --shutdown
Copy-Item `
"$env:USERPROFILE\Downloads\wsl.2.7.12.0.x64.msi" `
"$env:USERPROFILE\Downloads\wsl.msi" `
-Force

Step 4: Stop wsl:

wsl --shutdown

Step 5: Run:

msiexec /fvamus "$env:USERPROFILE\Downloads\wsl.msi" /passive /norestart /L*v C:\Temp\wsl-force-repair-2.log

Step 6: Verify the files are there:

PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Test-Path "C:\Program Files\WSL\system.vhd"
True
PS C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools> Test-Path "C:\Program Files\WSL\tools\modules.vhd"
True

Step 7: Launch WSL2:

wsl -d Ubuntu

Log: https://gist.github.com/siddhsql/2c2bfb6d53466ef013c8a7852f4fc0c9

Posted in Computers, programming, Software | Tagged | Leave a comment

Using certbot with cloudflare

I keep running into endless series of issues with certbot when it fails to renew a certificate etc. Recently I migrated my workflow to using the CloudFlare DNS authenticator. Pros and Cons of this approach:

Pros:

  • it completely decouples certbot from nginx which is the main reason that renewals fail. nginx is not running → renewal fails. nginx config is not correct → renewal fails. Whenever I edit nginx config I have to be careful not to break certbot. All this pain goes away.

Cons:

  • You have to migrate DNS to cloudflare, install a plugin, setup an API token. However, its one-time pain unlike the recurring pain above.

What the authenticator does?

When you use certbot you need to prove to it that you own the domain(s) for which you are requesting certificates. This can be done in various ways and there is an authenticator for each method. The Cloudflare DNS authenticator works by adding DNS records that provide proof of ownership to certbot. Here is essentially how it works:

  • certbot says add XYZ record to the DNS of the domain (xyz.com) for which you are trying to request the certificate. Since only the owner of the domain can modify its DNS, if the record is added it proves to certbot you indeed own the domain
  • the authenticator automatically adds the records to cloudflare – without you having to add them manually – this is where the API token (below) comes into the picture
  • certbot verifies the records are there and issues the certificate
  • the authenticator does a cleanup and removes the transient records added in step 1

What this means?

  • You will need to host your DNS on CloudFlare. They have a generous free plan. You do not need to change your domain registrar. You only need to update the DNS provider (CloudFlare becomes the DNS provider)
  • There is some software (certbot plugin that enables using CloudFlare for verification) you need to install on your webserver and I forget that now (see later)
  • You need to setup an API token on CloudFlare on https://dash.cloudflare.com/profile/api-tokens. What this token does? It allows the software to make changes to DNS on your behalf
  • Save the token on your webserver. I use the location /etc/letsencrypt/cloudflare/credentials.ini. Chmod this to 600

How to use it?

First do a dry-run:

sudo certbot certonly --cert-name optionswheel.net --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini --dns-cloudflare-propagation-seconds 120 -d optionswheel.net -d www.optionswheel.net --force-renewal --dry-run

If it succeeds, do the actual run by removing the --dry-run flag.

The --force-renewal flag will update any pre-existing renewal config that was using another authenticator. E.g., I was earlier using the webroot authenticator. The --force-renewal flag updated it to using the Cloudflare authenticator.

Gotchas

  • manually editing the renewal config does not work
  • running this command also does not update the renewal config
sudo certbot reconfigure --cert-name nuvoice.ai \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
--dns-cloudflare-propagation-seconds 120
  • what works is explicitly renewing certificates and adding the –force-renewal flag
  • don’t forget to re-start nginx after renewing the certificate (sudo nginx -t && sudo nginx -s reload)

Run a particular renewal config

sudo certbot renew --cert-name YOUR_CERT_NAME --dry-run

Sample Config

$ cat /etc/letsencrypt/renewal/xyz.conf
version = 5.7.0
archive_dir = /etc/letsencrypt/archive/xyz
cert = /etc/letsencrypt/live/xyz/cert.pem
privkey = /etc/letsencrypt/live/xyz/privkey.pem
chain = /etc/letsencrypt/live/xyz/chain.pem
fullchain = /etc/letsencrypt/live/xyz/fullchain.pem
[renewalparams]
account = 348...
authenticator = dns-cloudflare
server = https://acme-v02.api.letsencrypt.org/directory
key_type = ecdsa
dns_cloudflare_propagation_seconds = 120
dns_cloudflare_credentials = /etc/letsencrypt/cloudflare/credentials.ini
[acme_renewal_info]
ari_retry_after = 2026-08-20T02:12:43

note authenticator = dns-cloudflare which is the important part.

Official Docs:

The Cloudflare DNS Authenticator Plugin:

Let me know how it goes for you.

Posted in Computers, programming, Software | Leave a comment

How to Get Real Client IPs in Express Behind Cloudflare and Nginx (Without IP Spoofing)

If you are running an Express.js application behind a reverse proxy setup like Cloudflare → Nginx → Express, accurately identifying a visitor’s real IP address is critical. Whether you are enforcing rate limits, analyzing web traffic, or logging security events, relying on low-level socket properties like req.socket.remoteAddress will leave you seeing only Cloudflare’s or Nginx’s IP address.

Worse, misconfiguring proxy trust settings in Express can expose your application to IP spoofing attacks, allowing malicious actors to bypass rate limiters with forged headers.

Here is a breakdown of how the header chain works, why traditional setups fail, and how to safely configure Express with app.set('trust proxy', 2).


The Problem: Reverse Proxies and Header Chains

When a user visits your web application through Cloudflare and Nginx, the request travels through two distinct proxy hops before hitting your Node.js application:

  1. Client connects to Cloudflare (162.159.x.x)
  2. Cloudflare connects to your Nginx server (127.0.0.1)
  3. Nginx forwards the request to Express.js

If you query req.socket.remoteAddress inside Express, Node.js will report 127.0.0.1 (or Nginx’s local socket IP). If you do not evaluate proxy headers, your rate limiter will treat every user on the internet as a single visitor, quickly locking out legitimate traffic.

To pass the real client IP down the chain, proxies append client IP addresses to the X-Forwarded-For HTTP header.


Understanding the X-Forwarded-For Header

As a request moves through each proxy, the X-Forwarded-For header gets appended from left to right:

X-Forwarded-For: Client IP, Cloudflare IP

When Nginx receives the request from Cloudflare and passes it to Express via proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;, the full header reaching Express looks like this:

X-Forwarded-For: 203.0.113.195, 162.159.116.147

  • 203.0.113.195 is the real client IP attached by Cloudflare.
  • 162.159.116.147 is the Cloudflare edge proxy IP attached by Nginx.

The Vulnerability: Why app.set('trust proxy', true) Is Dangerous

A common solution in Express tutorials is to enable full proxy trust:

// DO NOT DO THIS IN PRODUCTION
app.set('trust proxy', true);

Setting trust proxy to true tells Express to trust every IP listed in the X-Forwarded-For chain without restriction, returning the leftmost IP as req.ip.

How Attackers Exploit This

If an attacker sends a request directly to your origin or through Cloudflare with a manually forged header:

X-Forwarded-For: 1.1.1.1, 2.2.2.2

  1. Cloudflare appends the attacker’s actual IP (198.51.100.5): X-Forwarded-For: 1.1.1.1, 2.2.2.2, 198.51.100.5
  2. Nginx appends Cloudflare’s IP (162.159.116.147): X-Forwarded-For: 1.1.1.1, 2.2.2.2, 198.51.100.5, 162.159.116.147
  3. With trust proxy: true, Express steps all the way back to the leftmost IP and resolves req.ip as 1.1.1.1.

By changing the fake IP in their request header on every hit, an attacker can trivially bypass custom rate limiters and IP-based blocking logic.


The Solution: Explicit Hop Counting with trust proxy: 2

Instead of trusting the entire header blindly, you can tell Express exactly how many proxy hops sit between it and the untrusted public internet.

In a Cloudflare → Nginx → Express stack, there are exactly 2 trusted hops:

  1. Hop 1 (Outer): Cloudflare
  2. Hop 2 (Inner): Nginx

To configure Express safely, explicitly set:

// Trust exactly 2 proxy hops back from Express
app.set('trust proxy', 2);

How Express Resolves req.ip with Hop Counting

When trust proxy is set to 2, Express evaluates the X-Forwarded-For chain starting from the right (the closest proxy) and steps back exactly 2 hops:

X-Forwarded-For: ["1.1.1.1", "2.2.2.2", "198.51.100.5", "162.159.116.147"]
                                         ▲               ▲
                                         │               └─ Hop 1 (Nginx)
                                         └─ Hop 2 (Cloudflare) -> Express selects THIS as req.ip

Express ignores 1.1.1.1 and 2.2.2.2 entirely because they lie outside the trusted 2-hop boundary. req.ip correctly resolves to 198.51.100.5 (the real client IP validated by Cloudflare).


Verifying Your Setup

You can verify how Express processes incoming IP chains by adding a temporary debugging middleware:

app.use((req, res, next) => {
  const rawXff = req.headers['x-forwarded-for'] || '';
  const xffArray = rawXff.split(',').map(ip => ip.trim());

  console.log('--- IP Resolution Debug ---');
  console.log(`Raw X-Forwarded-For Header : "${rawXff}"`);
  console.log(`Parsed IP Array            :`, xffArray);
  console.log(`Express Selected req.ip    : ${req.ip}`);
  console.log(`Direct Socket Remote IP    : ${req.socket.remoteAddress}`);
  console.log('---------------------------');

  next();
});

Key Rules to Remember

  • Always read req.ip in custom rate limiters or security tools—never read req.socket.remoteAddress directly when running behind a proxy.
  • Avoid app.set('trust proxy', true) in multi-tier architecture to prevent header injection vulnerabilities.
  • Match your trust proxy integer setting directly to the number of reverse proxy layers in your infrastructure (e.g., 1 for Nginx only, 2 for Cloudflare + Nginx).

As I was testing this setup I found that even though Express was logging the real client IP, NGINX was not. It turns out you also have to add following to the http block in /etc/nginx/nginx.conf for NGINX itself to log the real client IP in its logs:

http {

    # https://gemini.google.com/app/2722d33b9f3f1f27
    # Trust Cloudflare IPv4 ranges
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 131.0.72.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;

    # Trust Cloudflare IPv6 ranges
    set_real_ip_from 2400:cb00::/32;
    set_real_ip_from 2606:4700::/32;
    set_real_ip_from 2803:f800::/32;
    set_real_ip_from 2405:b500::/32;
    set_real_ip_from 2405:8100::/32;
    set_real_ip_from 2a06:98c0::/29;
    set_real_ip_from 2c0f:f248::/32;

    # Tell Nginx which header contains the real visitor IP
    real_ip_header CF-Connecting-IP;
}

Add this to /etc/nginx/nginx.conf so its available to all other configs without having to add to each one of them.

Posted in Computers, programming, Software | Tagged , | Leave a comment

Google Ads Tips

First of all I don’t recommend it. Its very difficult to setup and even after spending thousands of dollars I have yet to see any ROI – return on investment. It does all kinds of deceptive and misleading things. Still if you are compelled to use it, here are some tips to avoid shooting yourself in the foot:

  1. Do not use broad search or it will display your ad on completely irrelevant queries. Always use phrase match or exact match.
  2. If you are advertising a paid service (most likely) add free as a negative keyword
  3. Turn off display network or it will keep showing your ad on irrelevant pages
  4. If targetting a location make sure to unselect Presence or Interest. Only select Presence and even then it might not target the location and instead target all countries and territories
  5. Do not start with maximize conversions on a fresh campaign. Use Maximize clicks (even manual CPC is fine). Once you have 30+ conversions only then switch to maximize conversions so it knows how it can maximize. When you turn on maximize conversions on a fresh campaign with no conversion data it has no idea what clicks will lead to a conversion.

Understand the difference between search ads and display ads. From https://instapage.com/blog/search-ads-vs-display-ads:

  • The average Google Ads CPC is $2.41 for search network ads, and only $0.59 for display network ads
  • The average conversion rate across all industries is 4.40% for search campaigns, while the average for display campaigns is only 0.57%
  • search ads are a form of “pull” advertising while display ads are “push” advertising

Let me know in comments what you think.

Posted in Computers | Leave a comment

Cold Email Marketing

I am running a cold email outreach campaign. Does the daily volume of emails I send influence risk of my account getting flagged as spam?

Yes, the daily volume of cold emails you send significantly influences the risk of your account or domain getting flagged as spam. However, it’s not the only factor—sender behavior, reputation, and other practices play a bigger role in long-term deliverability.

Why Volume Matters

Email providers (Gmail, Outlook, Yahoo, etc.) and spam filters monitor patterns that distinguish legitimate senders from spammers:

  • Sudden spikes or high volumes mimic bulk/spammy behavior and can trigger filters, lower your sender reputation, and push emails to spam folders or cause blocks.
  • Consistency and gradual increases are safer. Abrupt jumps (e.g., from 10 to 200 emails/day) raise red flags more than steady, moderate volumes.
  • High volume amplifies other issues: poor engagement (low opens/replies), high bounce rates, or spam complaints quickly damage reputation. Even a few complaints can hurt your domain broadly.

Official ESP limits (e.g., Gmail ~2,000/day for Workspace, Outlook ~1,000) are for general use and far too high for cold outreach. Exceeding safe cold-email thresholds often leads to flags even if you’re under official caps.

Recommended Safe Daily Limits for Cold Emails (2026 Guidance)

These vary by domain age, warmup status, and setup, but common benchmarks include:

  • New/warming domains: Start at 5–20 emails per day per inbox and ramp up gradually (e.g., 10–25% or ~100% max increase per day/week).
  • Warmed/established inboxes: 30–100 cold emails per day per inbox is a common safe range. Some sources suggest capping at ~25–50 for Gmail to minimize risk.
  • Scaling higher: Use multiple inboxes/domains (e.g., 3–5+), dedicated warmup tools, and rotate sending to hit 500–2,000+/day total without burning one account.

Quality > Quantity: Well-personalized emails with good engagement outperform high-volume blasts. Generic or poorly targeted sends hurt more than raw numbers.

Other Key Factors That Influence Spam Risk

Volume interacts with these—high volume makes problems worse:

  • Account warmup: Essential for new domains/inboxes. Gradually build reputation with simulated positive interactions.
  • Authentication: Proper SPF, DKIM, DMARC setup is non-negotiable.
  • Content & compliance: Avoid spam triggers, include unsubscribe links, personalize, and follow CAN-SPAM/GDPR/etc.
  • Engagement & reputation: High reply/open rates help; complaints/bounces hurt.
  • Tools & infrastructure: Cold email platforms with warmup and monitoring are better than raw Gmail/Outlook for volume. Many marketing tools (Mailchimp, SendGrid) prohibit or heavily restrict true cold emails in their terms.

Best Practices to Minimize Risk

  • Warm up properly and ramp volume slowly.
  • Monitor metrics (deliverability, complaints, bounces) with tools.
  • Use dedicated domains for outreach (separate from your main business email).
  • Send at consistent times/cadences.
  • Focus on high-quality, targeted lists and valuable content.

In short, yes—pushing high daily volumes without proper setup greatly increases spam risk, but smart, gradual scaling with strong fundamentals can keep it manageable. Test small, monitor closely, and prioritize reputation over speed. If you’re scaling aggressively, consider professional cold email infrastructure.

Posted in Computers | Leave a comment