Powering Your Web Applications with Tengine/Nginx on Alibaba Cloud ECS

When deploying web applications or serving static content on an Alibaba Cloud ECS instance, a robust web server is crucial. Nginx is a popular high-performance web server, reverse proxy, and load balancer. Tengine, a fork of Nginx maintained by Taobao (Alibaba), offers additional features and optimizations, making it an excellent choice for demanding environments.

This guide will walk you through the key aspects of configuring Tengine/Nginx on your Alibaba Cloud Linux ECS instance and managing its service.

Prerequisites

  • An Alibaba Cloud ECS instance running a Linux distribution.
  • Root or sudo privileges.
  • Tengine (or Nginx) installed on your system. This guide focuses on configuration and management, assuming Tengine is installed (e.g., in /opt/tengine/).
  • Basic familiarity with Linux command-line operations.

1. Understanding Tengine/Nginx Installation (Brief Overview)

While this guide doesn't cover the detailed installation steps for Tengine, it's typically installed from source or specific repositories. A common installation path, as indicated in the configuration, is /opt/tengine/.

If you were to install Tengine from source, the general steps would involve:

  1. Downloading the Tengine source code.
  2. Installing build dependencies (like GCC, PCRE, zlib, OpenSSL).
  3. Configuring the build (./configure --prefix=/opt/tengine ...).
  4. Compiling (make).
  5. Installing (make install).

For this guide, we will assume Tengine is already installed and accessible.

2. The Core: Tengine/Nginx Configuration

The main configuration file for Tengine (similar to Nginx) dictates its behavior. In this setup, it's located at /opt/tengine/conf/nginx.conf.

Let's break down the provided example configuration:

# user  op; # Best practice: run Nginx worker processes as a non-privileged user.
worker_processes  1; # Number of worker processes, often set to the number of CPU cores.

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#error_log  "pipe:rollback logs/error_log interval=1d baknum=7 maxsize=2G"; # Advanced logging with rotation.
error_log  logs/error.log warn; # Set error log level to 'warn'.

pid        /opt/tengine/logs/nginx.pid; # Path to the PID file.

worker_rlimit_nofile 51200; # Maximum number of open files per worker process.

events {
    multi_accept on; # Workers accept all new connections at once.
    use epoll; # Use epoll for network I/O on Linux for better performance.
    worker_connections  51200; # Maximum number of simultaneous connections per worker.
}


http {
    server_tokens off; # Disable emitting Nginx version on error pages and in "Server" header.
    add_header X-Frame-Options SAMEORIGIN; # Prevents clickjacking.
    add_header X-Content-Type-Options nosniff; # Prevents MIME-sniffing.
    add_header X-XSS-Protection "1; mode=block"; # Enables XSS filtering.
    more_clear_headers 'Server'; # Completely removes the 'Server' header (Tengine specific or via module).

    include       mime.types; # Includes file extension to MIME type mappings.
    default_type  application/octet-stream; # Default MIME type.

    sendfile    on; # Enables sendfile() system call for faster static file serving.
    send_timeout  30; # Timeout for transmitting a response to the client.
    # fastcgi_buffers 8 128k;
    keepalive_timeout  30; # Timeout during which a keep-alive client connection will stay open.

    # server_names_hash_bucket_size 128;
    client_header_buffer_size 32k; # Buffer size for reading client request headers.
    large_client_header_buffers 4 32k; # Max number and size of buffers for large client request headers.
    client_max_body_size 8m; # Maximum allowed size of the client request body.
    client_body_buffer_size 512k; # Buffer size for reading client request body.

    # Proxy settings (commented out but good to know for reverse proxy setups)
    # proxy_connect_timeout 5;
    # proxy_read_timeout 30;
    # proxy_send_timeout 5;
    # proxy_buffer_size 16k;
    # proxy_buffers 4 64k;
    # proxy_busy_buffers_size 128k;
    # proxy_temp_file_write_size 128k;

    gzip  on; # Enables gzip compression.
    gzip_proxied any; # Compress data even for proxied requests.
    gzip_min_length  1k; # Minimum response length to gzip.
    gzip_buffers     4 16k; # Number and size of buffers for compression.
    gzip_http_version 1.1; # Gzip for HTTP/1.1 requests.
    gzip_comp_level 6; # Compression level (1-9).
    gzip_types text/plain application/json application/javascript application/x-javascript text/css application/xml text/javascript; # MIME types to compress.
    gzip_disable "MSIE [1-6]\."; # Disable gzip for old IE versions.
    gzip_vary on; # Adds "Vary: Accept-Encoding" header.

    charset utf-8; # Default charset.
    charset_types *; # Apply charset to all content types.

    # Default server block
    server {
      listen       80; # Listen on port 80 for IPv4.
      server_name  localhost; # Server name (can be IP or domain).

      location / {
        root   /opt/applications; # Root directory for requests to this location.
        index  index.html index.htm; # Default files to serve.
      }
    }

   # Include virtual host configurations from a separate directory
   # This is a best practice for managing multiple sites.
   include sites/xxx.domain.com.conf; # Note: .conf extension is a common convention
   include sites/xxx.domain2.com.conf;
   include sites/xxx.domain3.com.conf;
}

Key Configuration Highlights:

  • Security Headers: server_tokens off, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, and more_clear_headers 'Server' enhance security by hiding server details and protecting against common web vulnerabilities.
  • Performance: worker_processes, worker_connections, sendfile on, and gzip settings are crucial for handling traffic efficiently and reducing load times.
  • Modular Configuration: The include sites/*.conf; directive is highly recommended. It allows you to define each website or application (virtual host) in its own configuration file within the /opt/tengine/conf/sites/ directory. This keeps your main nginx.conf clean and makes site management easier.

For example, a file like /opt/tengine/conf/sites/example.com.conf might look like:

upstream my_hyperse_node {
  server  127.0.0.1:7001;
}
server {
  listen               80;
  access_log off;
  server_name          my.hyperse.net;
  return 301           https://my.hyperse.net$request_uri;
}
server {
  if ($host ~* ^www\.) {
    rewrite ^ $scheme://$host$request_uri permanent;
  }
  listen               443 ssl;
  server_name          oss.hyperse.net;
  ssl_certificate      sslkey/hyperse/www_hyperse_net.crt;
  ssl_certificate_key  sslkey/hyperse/www_hyperse_net.key;
  ssl_session_cache    shared:SSL:1m;
  ssl_session_timeout  5m;
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers  on;
  access_log off;

  location ~* \.(tpl|inc|cfg|less|scss)$ {
    deny all;
  }

  location ~ /\. {
    deny all;
    log_not_found off;
  }

  location = /robots.txt {
    alias /opt/applications/robots/disallow.txt;
  }

  location /favicon.ico {
    alias /opt/applications/favicon-oss/favicon.ico;
  }

  location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Host $host:$server_port;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://my_hyperse_node;
    proxy_redirect off;
  }
}

3. Managing the Tengine/Nginx Service with systemd

On modern Linux systems, systemd is used to manage services. Assuming you have a nginx.service (or tengine.service) unit file configured for your Tengine installation.

Check Service Status: To view the current status of the Nginx/Tengine service:

sudo systemctl status nginx

You should see output similar to this, confirming it's active (running) and pointing to your Tengine binaries:

● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2024-06-09 09:20:20 CST; 1 months 12 days ago
 Main PID: 2551738 (nginx) # This is the master process
    Tasks: 2 (limit: 100494)
   Memory: 31.7M
   CGroup: /system.slice/nginx.service
           ├─2551738 nginx: master process /opt/tengine/sbin/nginx -c /opt/tengine/conf/nginx.conf
           └─2551739 nginx: worker process

Notice how the master process path correctly points to /opt/tengine/sbin/nginx and uses the configuration file from /opt/tengine/conf/nginx.conf.

Restarting the Service: If you make changes to your configuration files, you'll need to restart or reload Tengine/Nginx for them to take effect.

sudo systemctl restart nginx.service

A restart will stop and then start the service. For configuration changes, a reload is often preferred as it applies changes without dropping active connections:

sudo systemctl reload nginx.service

Before reloading or restarting, it's always a good idea to test your configuration:

sudo /opt/tengine/sbin/nginx -t -c /opt/tengine/conf/nginx.conf
# Or if nginx is in your PATH and aliased to tengine's binary
# sudo nginx -t

Other Common Service Commands:

  • Start the service: sudo systemctl start nginx.service
  • Stop the service: sudo systemctl stop nginx.service
  • Enable service on boot: sudo systemctl enable nginx.service
  • Disable service on boot: sudo systemctl disable nginx.service

View All Started Services: To see a list of all active services managed by systemd:

systemctl list-units --type=service --state=running

Or simply for all loaded service units:

systemctl list-units --type=service

4. Testing Your Setup

After configuring and starting Tengine/Nginx:

  1. Local Test:

    curl http://localhost
    

    This should return the index.html from /opt/applications (or whatever your default server block is configured to serve).

  2. External Test: Access http://<your_ecs_public_ip> from a web browser on another machine.

    • Important: Ensure that port 80 (for HTTP) or port 443 (for HTTPS) is open in your Alibaba Cloud ECS instance's Security Group rules.

Conclusion

You've now explored the key configuration aspects of Tengine/Nginx on an Alibaba Cloud ECS instance, focusing on a robust nginx.conf structure and service management using systemd. By leveraging Tengine's capabilities and maintaining a well-organized configuration, you can reliably serve your web applications and content with high performance and security. Remember to regularly review and update your configurations and keep your Tengine/Nginx software up to date.

Community

We're excited to see the community adopt Hyperse-io, raise issues, and provide feedback. Whether it's a feature request, bug report, or a project to showcase, please get involved!