Contents

Compiling Nginx from Source: Understanding Module Architecture and Custom Extensions

Most people install Nginx via package managers, but compiling from source truly reveals its module mechanism. This post uses FastDFS module integration as an example to analyze Nginx’s build system and modular architecture.

1. Why Compile from Source?

1.1 Package Manager Limitations

1
2
3
4
5
6
# Package manager install
apt install nginx

# Check compile parameters
nginx -V
# Fixed module list, can't modify

Problems:

  • Can’t add third-party modules (FastDFS, OpenResty)
  • Can’t remove unneeded modules (reduce size)
  • Can’t tune compilation optimization flags

1.2 Scenarios Requiring Source Compilation

ScenarioRequirement
Distributed file storageIntegrate fastdfs-nginx-module
WAF protectionIntegrate ModSecurity
High-performance cacheIntegrate ngx_cache_purge
Lua scriptingIntegrate OpenResty
Minimal footprintRemove unneeded modules

2. Nginx Modular Architecture

2.1 Module Categories

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
┌─────────────────────────────────────────────────────────┐
│                     Nginx Core                          │
├─────────────────────────────────────────────────────────┤
│  Core Modules                                            │
│  ├── ngx_core_module    Process management, config parse │
│  ├── ngx_errlog_module  Error logging                    │
│  └── ngx_events_module  Event-driven                     │
├─────────────────────────────────────────────────────────┤
│  HTTP Modules                                            │
│  ├── ngx_http_core_module         HTTP core              │
│  ├── ngx_http_proxy_module        Reverse proxy          │
│  ├── ngx_http_fastcgi_module      FastCGI support        │
│  ├── ngx_http_gzip_module         Gzip compression       │
│  └── ngx_http_ssl_module          HTTPS support          │
├─────────────────────────────────────────────────────────┤
│  Third-party Modules                                     │
│  ├── fastdfs-nginx-module         FastDFS integration    │
│  ├── ngx_cache_purge              Cache purging          │
│  └── lua-nginx-module             Lua scripting          │
└─────────────────────────────────────────────────────────┘

2.2 Module Loading Mechanism

Nginx modules can be statically compiled or dynamically loaded:

1
2
3
4
5
6
7
8
# Static compilation: linked into binary at compile time
./configure --add-module=/path/to/module

# Dynamic loading (1.9.11+): loaded at runtime
./configure --add-dynamic-module=/path/to/module

# Load dynamic module in nginx.conf
load_module modules/ngx_http_image_filter_module.so;

3. Build Environment Preparation

3.1 Install Dependencies

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Ubuntu/Debian
sudo apt update
sudo apt install -y \
    build-essential \
    libpcre3-dev \
    zlib1g-dev \
    libssl-dev \
    libgd-dev \
    libgeoip-dev

# CentOS/RHEL
sudo yum groupinstall -y "Development Tools"
sudo yum install -y \
    pcre-devel \
    zlib-devel \
    openssl-devel \
    gd-devel \
    GeoIP-devel

3.2 Dependency Explanation

DependencyPurposeCorresponding Module
PCRERegular expressionsrewrite module
zlibGzip compressiongzip module
OpenSSLHTTPSssl module
libgdImage processingimage_filter module
GeoIPIP geolocationgeoip module

4. Configure Script Deep Dive

4.1 Common Parameters

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
./configure \
    # Install paths
    --prefix=/usr/local/nginx \
    --sbin-path=/usr/local/nginx/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --pid-path=/var/run/nginx.pid \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    
    # User and group
    --user=nginx \
    --group=nginx \
    
    # Enable modules
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_realip_module \
    --with-http_gzip_static_module \
    --with-http_stub_status_module \
    
    # Disable unneeded modules (reduce size)
    --without-http_autoindex_module \
    --without-http_ssi_module \
    
    # Third-party modules
    --add-module=/path/to/fastdfs-nginx-module/src \
    
    # Compilation optimization
    --with-cc-opt='-O2 -fstack-protector-strong' \
    --with-ld-opt='-Wl,-z,relro -Wl,-z,now'

4.2 What Does Configure Do?

1
2
3
# View configure output
ls objs/
# autoconf.err  Makefile  ngx_auto_config.h  ngx_modules.c  src/

Key files:

FilePurpose
objs/MakefileBuild rules
objs/ngx_auto_config.hAuto-detected system config
objs/ngx_modules.cModule registration list

4.3 Module Registration Internals

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// objs/ngx_modules.c (auto-generated)
ngx_module_t *ngx_modules[] = {
    &ngx_core_module,
    &ngx_errlog_module,
    &ngx_conf_module,
    &ngx_events_module,
    &ngx_http_module,
    &ngx_http_core_module,
    // ... more modules
    &ngx_http_fastdfs_module,  // Third-party module
    NULL
};

This is why adding modules requires recompilation — the module list is determined at compile time.

5. FastDFS Module Integration

5.1 Preparation

1
2
3
4
5
6
7
# Download source
wget https://nginx.org/download/nginx-1.24.0.tar.gz
git clone https://github.com/happyfish100/fastdfs-nginx-module.git

# Extract
tar -xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0

5.2 Configure Build

1
2
3
4
5
6
7
./configure \
    --prefix=/usr/local/nginx \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_realip_module \
    --with-http_stub_status_module \
    --add-module=../fastdfs-nginx-module/src

5.3 Compile and Install

1
2
3
4
5
6
7
8
9
# Compile (use all CPU cores)
make -j$(nproc)

# Install
sudo make install

# Verify
/usr/local/nginx/sbin/nginx -V
# Output should include --add-module=.../fastdfs-nginx-module

5.4 Configure FastDFS Module

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# /etc/nginx/nginx.conf
http {
    server {
        listen 80;
        
        # FastDFS file access
        location /group1/M00 {
            ngx_fastdfs_module;
        }
    }
}

6. Compilation Optimization Strategies

6.1 Performance Optimization Flags

1
2
3
4
5
6
./configure \
    # Compiler optimization
    --with-cc-opt='-O3 -march=native -mtune=native' \
    
    # Linker optimization
    --with-ld-opt='-Wl,-O1 -Wl,--as-needed'

Optimization level explanation:

FlagEffectUse Case
-O0No optimizationDebugging
-O2Balanced optimizationProduction (recommended)
-O3Aggressive optimizationMaximum performance
-march=nativeTarget current CPUNon-container environments

6.2 Security Hardening

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
./configure \
    # Stack protection
    --with-cc-opt='-fstack-protector-strong -D_FORTIFY_SOURCE=2' \
    
    # RELRO (lazy binding protection)
    --with-ld-opt='-Wl,-z,relro -Wl,-z,now' \
    
    # PIE (address space randomization)
    --with-cc-opt='-fPIE' \
    --with-ld-opt='-pie'

6.3 Slim Binary

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Remove unneeded modules
./configure \
    --without-http_autoindex_module \
    --without-http_browser_module \
    --without-http_empty_gif_module \
    --without-http_geo_module \
    --without-http_map_module \
    --without-http_split_clients_module \
    --without-http_userid_module

# Strip symbol table after compile
strip /usr/local/nginx/sbin/nginx

# Compare size
ls -lh /usr/local/nginx/sbin/nginx
# From ~5MB to ~1.5MB

7. Production Deployment

7.1 Systemd Service File

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# /etc/systemd/system/nginx.service
[Unit]
Description=Nginx HTTP Server
After=network.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

7.2 Zero-Downtime Upgrade

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 1. Compile new version (don't install)
./configure ... && make

# 2. Backup old binary
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old

# 3. Replace binary
cp objs/nginx /usr/local/nginx/sbin/nginx

# 4. Send USR2 to old process, start new process
kill -USR2 $(cat /var/run/nginx.pid)

# 5. Gracefully shut down old workers
kill -WINCH $(cat /var/run/nginx.pid.oldbin)

# 6. After confirming success, stop old master
kill -QUIT $(cat /var/run/nginx.pid.oldbin)

8. Troubleshooting

8.1 Compilation Error Debugging

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# View detailed errors
cat objs/autoconf.err

# Common issues
# 1. Missing PCRE
./configure: error: the HTTP rewrite module requires the PCRE library
# Solution: apt install libpcre3-dev

# 2. Missing OpenSSL
./configure: error: SSL modules require the OpenSSL library
# Solution: apt install libssl-dev

# 3. Third-party module path wrong
./configure: error: no /path/to/module/config was found
# Solution: Check if config file exists in module directory

8.2 Runtime Debugging

1
2
3
4
5
6
7
8
# Test configuration
nginx -t

# View loaded modules
nginx -V 2>&1 | tr ' ' '\n' | grep module

# Start in debug mode
nginx -g "daemon off; error_log /dev/stderr debug;"

9. Summary

TopicTakeaway
Module mechanismStatic compile vs dynamic load
ConfigureAuto-detect + generate Makefile
Compile optimization-O2 + security hardening flags
Zero-downtime upgradeUSR2 + WINCH signals

Core insight: Understanding Nginx’s build system not only enables flexible customization, but also deepens understanding of C project build processes — applicable to other system software like Redis and Linux Kernel.