Search This Blog

Showing posts with label Nginx. Show all posts
Showing posts with label Nginx. Show all posts

Wednesday, August 26, 2026

Turbocharging Nginx on Oracle Cloud ARM: Zero-Copy HTTPS with Kernel TLS (kTLS)

Turbocharging Nginx on Oracle Cloud ARM: Zero-Copy HTTPS with Kernel TLS (kTLS)

If you run high-concurrency web applications, media assets, or content management systems like WordPress on Oracle Cloud Infrastructure (OCI) Ampere Altra (ARM64) instances, you are already benefiting from high core counts and efficient compute.

However, serving static assets over HTTPS standardly incurs an invisible system tax: redundant memory copying and excessive CPU context switches.

By offloading symmetric TLS record processing directly to the Linux kernel via Kernel TLS (kTLS), you unlock true zero-copy sendfile() over HTTPS, slashing CPU overhead and maximizing throughput on Ubuntu 24.04 LTS.


The Hidden Bottleneck of User-Space HTTPS

In a traditional Nginx setup serving encrypted traffic:

[Disk / Page Cache] ──(Copy 1)──> [User Space: Nginx / OpenSSL]
                                           │
                                    (Encrypts Data)
                                           │
[Network Interface (NIC)] <──(Copy 2)── [Kernel Socket Buffer]
  1. The kernel reads requested files from disk or page cache into user-space memory buffers.
  2. OpenSSL in user space encrypts the payload block by block.
  3. Encrypted buffers are copied across the user/kernel space boundary into socket buffers.
  4. The network stack finally transmits the packets over the wire.

Because OpenSSL processes symmetric encryption in user space, the Linux kernel's high-performance sendfile() syscall is disabled for HTTPS. Every static asset—images, cached HTML, CSS, JavaScript, and binaries—triggers double memory copies and CPU cache invalidations.


How kTLS Solves the Problem

Kernel TLS cleanly separates the control plane from the data plane:

  • Handshake (Control Plane): Remains entirely in user space. OpenSSL handles certificate validation, key exchange, and session negotiation.
  • Data Plane (Encryption/Decryption): Once session keys are derived, OpenSSL passes them to the kernel via socket options (setsockopt(..., SOL_TLS, ...)). The socket switches to the tls Upper Layer Protocol (ULP).
[Disk / Page Cache] ──(In-Kernel Zero-Copy sendfile)──> [Kernel Crypto: ARM CE] ──> [NIC]

With kTLS active, Nginx issues a standard sendfile() syscall over HTTPS. The kernel reads directly from page cache, applies symmetric encryption (AES-GCM or ChaCha20-Poly1305) in-kernel using ARMv8 Neoverse N1 Cryptographic Extension instructions, and streams packets directly to the network interface. Zero user-space memory copies.


Prerequisites on Ubuntu 24.04 LTS (ARM64)

  • OS: Ubuntu 24.04 LTS (Kernel 6.8+ with CONFIG_TLS=m enabled by default)
  • Hardware: OCI Ampere Altra (ARMv8.2+ with hardware-accelerated AES/SHA Cryptographic Extensions)
  • Software: Nginx with OpenSSL 3.x

Step-by-Step Implementation & Common Pitfalls

1. Load and Persist the Kernel Module

The tls module is included in Ubuntu 24.04 but must be loaded:

# Load module immediately
sudo modprobe tls

# Persist module across reboots
echo "tls" | sudo tee /etc/modules-load.d/ktls.conf

Verify that the module is loaded:

lsmod | grep tls

2. The Nginx Configuration Pitfall

Many online guides suggest adding this directive to /etc/nginx/nginx.conf:

ssl_conf_cmd Options KTLS;

On standard Ubuntu 24.04 builds, running nginx -t will often throw an error:

[emerg] unknown directive "ssl_conf_cmd" in /etc/nginx/nginx.conf
nginx: configuration file /etc/nginx/nginx.conf test failed

The Fix: Do not place ssl_conf_cmd in Nginx. Instead, configure OpenSSL 3.x system-wide so all Nginx worker processes automatically use kTLS.

3. Enable kTLS via OpenSSL 3.x Configuration

Open /etc/ssl/openssl.cnf:

sudo nano /etc/ssl/openssl.cnf

Step A: Locate the existing [openssl_init] block (around line 43) and add ssl_conf = ssl_sect:

[openssl_init]
providers = provider_sect
ssl_conf = ssl_sect

Step B: Scroll to the very bottom of the file and append the SSL section:

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
CipherString = DEFAULT:@SECLEVEL=2
Options = KTLS

Save and exit the file.

4. Configure Nginx and Restart

Ensure your /etc/nginx/nginx.conf has sendfile and modern TLS protocols enabled:

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # ... remaining server configurations ...
}

Test configuration and restart the service:

sudo nginx -t && sudo systemctl restart nginx

Verifying kTLS in Production

Generate test HTTPS traffic against your server:

curl -k -o /dev/null https://127.0.0.1/

1. Check Kernel TLS Statistics

Inspect the kernel's real-time TLS statistics:

cat /proc/net/tls_stat

Key counters to watch:

  • TlsTxSw: Increments with every TLS record encrypted via software crypto routines in the kernel.
  • TlsCurrTxSw: Shows currently active kernel TLS transmit sockets.

2. Inspect Active Socket Offload

Run ss to verify that active connections use the TLS Upper Layer Protocol:

ss -ti '( sport = :443 or dport = :443 )'

Look for ulp:tls in the socket options output.


Performance Comparison

Metric Standard TLS (User Space) Kernel TLS (kTLS Zero-Copy)
Data Path 2 Buffer Copies (Kernel $\rightarrow$ User $\rightarrow$ Kernel) 0 Copies (Direct Page Cache $\rightarrow$ NIC)
sendfile() Syscall Disabled for HTTPS Fully Supported
CPU Overhead High %usr (User space encryption) Low %usr, shifts cleanly to %sys
Throughput Memory bandwidth bound Line-rate network bound

Summary

Enabling kTLS on Oracle Cloud ARM instances is a zero-cost optimization that yields substantial returns for static file delivery. By fixing the OpenSSL 3.x system configuration on Ubuntu 24.04, you eliminate user-space copy bottlenecks and allow the ARM Neoverse crypto engine to process encrypted traffic at native line rates.

Thursday, April 4, 2019

WordPress new post editor has encountered an unexpected error

I tried:

  • Disabled all plugins (included SEO) and browser addons.
  • Attempt recovery doesn't work. Error code.
  • Switch to other themes.

Error Code:

TypeError: Cannot read property 'show_ui' of undefined
    at https://www.milliondollarserver.com/wp-includes/js/dist/editor.min.js?ver=9.0.11:55:241342
    at i (https://www.milliondollarserver.com/wp-includes/js/dist/vendor/lodash.min.js?ver=4.17.11:6:91)
    at An.filter (https://www.milliondollarserver.com/wp-includes/js/dist/vendor/lodash.min.js?ver=4.17.11:99:338)
    at https://www.milliondollarserver.com/wp-includes/js/dist/editor.min.js?ver=9.0.11:55:241307
    at ph (https://www.milliondollarserver.com/wp-includes/js/dist/vendor/react-dom.min.js?ver=16.6.3:97:88)
    at eg (https://www.milliondollarserver.com/wp-includes/js/dist/vendor/react-dom.min.js?ver=16.6.3:125:307)
    at fg (https://www.milliondollarserver.com/wp-includes/js/dist/vendor/react-dom.min.js?ver=16.6.3:126:168)
    at wc (https://www.milliondollarserver.com/wp-includes/js/dist/vendor/react-dom.min.js?ver=16.6.3:138:237)
    at fa (https://www.milliondollarserver.com/wp-includes/js/dist/vendor/react-dom.min.js?ver=16.6.3:137:115)
    at ng (https://www.milliondollarserver.com/wp-includes/js/dist/vendor/react-dom.min.js?ver=16.6.3:149:69)

Environment
  • WordPress 5.1.1
  • Nginx 1.15
  • PHP-FPM 7.2
  • wp-supercache
Here is how I fix it:
#vi /etc/nginx/wp-supercache
Original:

location / {
    try_files $cachefile $uri $uri/ /index.php;
}
Changed to:
location / {
	try_files $cachefile $uri $uri/ /index.php$is_args$args;
}
Restart Nginx to apply the changes:
# sudo systemctl restart nginx
Related Bug: https://github.com/WordPress/gutenberg/issues/9912

Saturday, March 23, 2019

CREATE A LEMP STACK IN AWS EC2 by Amazon Linux 2 (LINUX, NGINX, MARIADB AND PHP 7.2)

Launch Instance: latest Amazon Linux 2 AMI



# Update Linux and install essential packages
sudo yum -y update

# Install php72 using amazon-linux-extras
sudo amazon-linux-extras install php7.2

# Install Nginx 1.12 using amazon-linux-extras
sudo amazon-linux-extras install nginx1.12

# Install mariadb using amazon-linux-extras
sudo amazon-linux-extras install lamp-mariadb10.2-php7.2
## this will install apache/httpd as well, which we don't need.
### uninstall httpd
sudo yum earse httpd httpd-tools
# install mariadb-server should be version 10.2 or higher
sudo yum install mariadb-server
To enable nginx, php-fpm and mardb services on boot:
sudo systemctl enable nginx
sudo systemctl enable php-fpm
sudo systemctl enable mariadb
To start all 3 service:
sudo systemctl start php-fpm
sudo systemctl start nginx
sudo systemctl start mariadb
sudo mysql_secure_installation

Wednesday, October 3, 2018

Debian 9 unattended upgrades Nginx and PHP 7 repo apt

I install Nginx mainline version from Nginx's officel Repo. PHP 7.2 FPM from packages.sury.org. In order to let the unattended upgrades do the work for me.
  1. I add /etc/apt/apt.conf.d/50unattended-upgrades
  2. Unattended-Upgrade::Origins-Pattern {
      ...
            "origin=nginx,label=nginx";
            "site=packages.sury.org";
    };
    
  3. Testing it out
  4. # unattended-upgrade --debug --dry-run
    Initial blacklisted packages: 
    Initial whitelisted packages: 
    Starting unattended upgrades script
    Allowed origins are: ['origin=Debian,codename=stretch,label=Debian-Security', 'origin=nginx,label=nginx', 'site=packages.sury.org']
    pkgs that look like they should be upgraded: 
    Fetched 0 B in 0s (0 B/s)                                                                                                                                             
    fetch.run() result: 0
    blacklist: []
    whitelist: []
    No packages found that can be upgraded unattended and no pending auto-removals
    

Friday, February 24, 2017

HHVM 3.18.0 crash on Ubuntu 16.04 with Nginx

Just try to bring up an new HHVM host on Ubuntu 16.04 with Nginx.

But HHVM keep crush error in /var/log/hhvm/error.log
It created error log in /tmp

Here is a example:


ProcessID: 1549
ThreadID: 140594705856256
ThreadPID: 2188
Name: unknown program
Type: Aborted
Runtime: hhvm
Version: tags/HHVM-3.18.0-0-g9b285191feb2bb1558bb6682da135263bd2a9e60
DebuggerCount: 0

ThreadType: Web Request
Assertion Message: Failed to initialize central HHBC repository:
Failed to initialize schema in /var/run/hhvm/hhvm.hhbc(rw-r--r-- root:root):
Failed to open /var/www/.hhvm.hhbc: 14 - unable to open database file

Assertion Failure: /tmp/tmp.Fv54re7NgD/hphp/runtime/vm/repo.cpp:562: HPHP::Repo::initCentral()::__lambda62: assertion `false' failed.
URL: /wp-admin/admin-ajax.php



Run ls -alt /var/run/hhvm
Since upgrading to 3.18, hhvm is unable to open hhvm.hhbc as it is created as root instead of www-data.

For now the workaround is to add the following to your configuration: /etc/hhvm/server.ini


hhvm.repo.central.file_user=www-data
hhvm.repo.central.file_group=www-data
hhvm.repo.central.file_mode=493



Restart the HHVM service.

And it works.

Hope HHVM team can fix it in the next release.


Reference: https://github.com/facebook/hhvm/issues/7674

Wednesday, April 27, 2016

Nginx upgrade to new stable 1.10 switch spdy to http2

nginx just release 1.10 stable.

After upgrade on my Debian server hosting the Milliondollarserver.com, it shows error message:

nginx: [warn] invalid parameter "spdy": ngx_http_spdy_module was superseded by ngx_http_v2_module in /etc/nginx/sites-enabled/milliondollarserver.com_ssl:4



My old /etc/nginx/sites-enabled/milliondollarserver.com_ssl config file is:
server {
listen 443 ssl spdy;


replace spdy by http2, restart the service.

server {
listen 443 ssl http2;



/etc/nginx/sites-enabled# service nginx restart


Everything goes normal.

Please let me know if you have any difficult on HTTP2.

Monday, April 4, 2016

Nginx Buffer messages in log keeps POST requests how to turned it off

2016/04/04 12:38:22 [warn] 1753#0: *512 a client request body is buffered to a temporary file /var/cache/nginx/client_temp/0000000044, client: 67.55.28.159, server: caramelkate.com, request: "POST /wp-admin/async-upload.php HTTP/1.1", host: "caramelkate.com", referrer: "https://caramelkate.com/wp-admin/post.php?post=1619&action=edit"

First I try to set the buffer same, but it's not working:

    client_body_buffer_size     10M;
client_max_body_size 10M;

Reference:http://serverfault.com/questions/511789/nginx-client-request-body-is-buffered-to-a-temporary-file

Then I try to increase the size of the buffer only for /wp-admin:

location /wp-admin {
client_body_buffer_size 100M;
}


Still not luck.


At last I go to Nginx's doc site: http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size

Syntax:	client_max_body_size size;
Default:
client_max_body_size 1m;
Context: http, server, location
Sets the maximum allowed size of the client request body, specified in the “Content-Length” request header field. If the size in a request exceeds the configured value, the 413 (Request Entity Too Large) error is returned to the client. Please be aware that browsers cannot correctly display this error. Setting size to 0 disables checking of client request body size.


If you want to ensure that the client request body is not buffered to
disk, you want to make sure that your client_body_buffer_size is larger
than your client_max_body_size. And be willing to refuse any client
request body bigger than that.

client_max_body_size  0;



So this is what my nginx vhost config file looks like:


client_body_buffer_size 10M;
client_max_body_size 0;

Monday, September 22, 2014

Fix HHVM 3.3 Bad Gateway error Debian Ubuntu

Found HHVM upgrade to 3.3 on Ubuntu Server 14.04 LTS:

Current status: 2 updates [+2], 33 new [+2].

The following packages will be upgraded:
hhvm linux-firmware
2 packages upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 31.7 MB of archives. After unpacking 11.3 kB will be used.
Do you want to continue? [Y/n/?] y
Get: 1 http://ca.archive.ubuntu.com/ubuntu/ trusty-updates/main linux-firmware all 1.127.6 [20.1 MB]
Get: 2 http://dl.hhvm.com/ubuntu/ trusty/main hhvm amd64 3.3.0~trusty [11.6 MB]
Fetched 31.7 MB in 9s (3,221 kB/s)
(Reading database ... 57804 files and directories currently installed.)
Preparing to unpack .../hhvm_3.3.0~trusty_amd64.deb ...
********************************************************************
* HHVM is being removed. You can remove it from your webserver with:
*
* $ sudo /usr/share/hhvm/uninstall_fastcgi.sh
* $ sudo /etc/init.d/nginx restart
* $ sudo /etc/init.d/apache restart
********************************************************************
Unpacking hhvm (3.3.0~trusty) over (3.2.0~trusty) ...
Preparing to unpack .../linux-firmware_1.127.6_all.deb ...
Unpacking linux-firmware (1.127.6) over (1.127.5) ...
Processing triggers for ureadahead (0.100.0-16) ...
Setting up hhvm (3.3.0~trusty) ...
update-alternatives: using /usr/bin/hhvm to provide /usr/bin/php (php) in auto mode
********************************************************************
* HHVM is installed.
*
* Running PHP web scripts with HHVM is done by having your webserver talk to HHVM
* over FastCGI. Install nginx or Apache, and then:
* $ sudo /usr/share/hhvm/install_fastcgi.sh
* $ sudo /etc/init.d/hhvm restart
* (if using nginx) $ sudo /etc/init.d/nginx restart
* (if using apache) $ sudo /etc/init.d/apache restart
*
* Detailed FastCGI directions are online at:
* https://github.com/facebook/hhvm/wiki/FastCGI
*
* If you're using HHVM to run web scripts, you probably want it to start at boot:
* $ sudo update-rc.d hhvm defaults
*
* Running command-line scripts with HHVM requires no special setup:
* $ hhvm whatever.php
*
* You can use HHVM for /usr/bin/php even if you have php-cli installed:
* $ sudo /usr/bin/update-alternatives --install /usr/bin/php php /usr/bin/hhvm 60
********************************************************************


The web server shows: Bad Gateway.

Try restart HHVM:

# service hhvm restart
* Restarting HHVM FastCGI Daemon hhvm
/usr/bin/hhvm: error while loading shared libraries: libgmp.so.10: cannot open shared object file: No such file or directory


Install libgmp10 package, restart HHVM solve the problem:

# aptitude install libgmp10
The following NEW packages will be installed:
libgmp10
0 packages upgraded, 1 newly installed, 0 to remove and 0 not upgraded.

# service hhvm restart
* Restarting HHVM FastCGI Daemon hhvm

Monday, June 23, 2014

Nginx 1.6 stable fail php-fpm on Debian Wheezy

I am big fan of Debian.
It just easy to setup a nice clean server get the job done.

For more effective web server, I try to use Nginx + PHP5-FPM to serve Wordpress and Mediawiki.

I bring up a new Debian Wheezy 7.5 64-bit server today.

1.First upgrade all new patch:
aptitude update && aptitude upgrade

2.Install Nginx Stable follow Nginx's offical Pre-Built Packages:
http://nginx.org/en/linux_packages.html#stable
wget http://nginx.org/keys/nginx_signing.key
apt-key add nginx_signing.key
aptitude update
aptitude install nginx

3.Install Latest MariaDB Pre-Built Packages:
aptitude install python-software-properties
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db
add-apt-repository 'deb http://ftp.osuosl.org/pub/mariadb/repo/10.0/debian wheezy main'
aptitude install mariadb-server

4.Install PHP5-FPM:
aptitude install php5-fpm

5.Modify Nginx vhost location in /etc/nginx/nginx.conf:
include /etc/nginx/sites-enabled/*.conf;

6.Put my vhost file at /etc/nginx/sites-available/mds.conf:
server {
listen 80;
server_name localhost;

access_log /var/log/nginx/log/mds.access.log main;
error_log /var/log/nginx/log/mds.error.log error;

root /var/www/mds;
index index.php index.html index.htm;

location / {
try_files $uri $uri/ /index.html;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/mds;
}

# With php5-fpm / php5-cgi will be different:
location ~ .php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}

Make a link:
ln -s /etc/nginx/sites-available/mds.conf /etc/nginx/sites-enable/

Restart Nginx:
service nginx restart

Then I put a index.php with phpinfo() into the /var/www/mds folder.
But the browser shows blank page.
I try follow different post, able to bring errors logs: php5-fpm.sock failed (13: Permission denied) error

But still not able to quickly fix it.

Spend almost half hour on it, finally found:

Missing this line in /etc/nginx/fastcgi_params:
fastcgi_param   SCRIPT_FILENAME         $request_filename;

I should just stay with Debian Nginx 1.2, what a wast!
Nginx's RPM package works just fine.

Hope this helps.

Update 1 on June 24, 2014:

It seems more problem are coming, I really miss stock debian package.

Php page show error, but nothing in error log file.

I have to run this to bring the php page up:
chmod 666 /var/run/php5-fpm.sock

Thanks the post: http://www.nginxtips.com/php5-fpm-sock-failed-13-permission-denied-error/

I modified file: /etc/php5/fpm/pool.d/www.conf
;listen.owner = www-data
;listen.group = www-data
;listen.mode = 0660
listen.owner = nginx
listen.group = nginx

service php5-fpm restart

Update 2: Additional installation to make it works better
aptitude install php-apc
aptitude install php5-mysqlnd
mysql_secure_installation


Update 2 on November 14, 2014:

Another solution for .sock permission issue will be:

/etc/nginx/nginx.conf
#user nginx;
user www-data;


This because php5-fpm package set /var/www owner to www-data.
It will be much cleaner just set nginx run as www-data, therefor we borrow the Debian setting over.

[poll id="2"]