Tuesday, 14 January 2025

Golang Gin: Implementing Interfaces

 interfaces define a set of methods. Any type that implements these methods satisfies the interface.

Example of an Interface Implementation:

package main ========================== import "fmt" // Interface definition type Printable interface { PrintInfo() string } ========================== // Struct that implements the interface type User struct { Name string Email string } ========================== // Implement the interface func (u User) PrintInfo() string { return fmt.Sprintf("Name: %s, Email: %s", u.Name, u.Email) } ========================== func main() { user := User{Name: "Le Giang", Email: "le.giang@example.com"} var p Printable = user // User satisfies the Printable interface fmt.Println(p.PrintInfo()) }

Output:

Name: Le Giang, Email: le.giang@example.com

Golang Gin: Composition Instead of Inheritance

Composition Instead of Inheritance

In Go, you can "extend" functionality by embedding structs. When a struct embeds another struct, it inherits its methods and fields.

Example of Composition (Struct Embedding):

package main =========================== import "fmt" // Base struct type Base struct { ID int } // Method of Base struct func (b *Base) PrintID() { fmt.Printf("ID: %d\n", b.ID) } =========================== // Extended struct using composition type Extended struct { Base // Embedding Base struct Name string }
=========================== func main() { // Initialize Extended ext := Extended{ Base: Base{ID: 42}, Name: "Le Giang", } // Access methods from Base ext.PrintID() // Access field from Extended fmt.Println("Name:", ext.Name) }

Output:

ID: 42 Name: Le Giang

Thank

Folder structure often used with Gin

Below is an example of a folder structure often used with Gin in large-scale projects. Gin itself does not enforce a strict layout, because it follows a minimalistic philosophy. However, the community usually follows certain best practices to keep the code organized.

my-gin-app/
├── cmd/
│   └── server/
│       └── main.go
├── config/
│   └── config.go
├── controllers/    (or handlers/)
│   └── user_controller.go
├── middlewares/
│   └── auth.go
├── models/
│   └── user.go
├── routes/
│   └── router.go
├── services/       (business logic)
│   └── user_service.go
├── repository/     (DB access, optional)
│   └── user_repository.go
├── go.mod
└── go.sum

Directory Overview (Suggested)

  1. cmd/server/main.go

    • The application’s entry point.
    • Initializes the Gin engine, loads configs, sets up routes, etc.
    • Placing main.go inside cmd/server/ is a common Go convention to keep the root clean.
  2. config/

    • Handles configuration (e.g., reading .env, using Viper, etc.).
    • For instance, config.go might have func InitConfig() to load environment variables or database connection info.
  3. controllers/ (or handlers/)

    • Houses functions that handle requests (CRUD, login, etc.).
    • Example: user_controller.go has func GetUsers(c *gin.Context) and func CreateUser(c *gin.Context).
  4. middlewares/

    • Contains middleware (auth, logging, recovery, etc.).
    • Example: auth.go with func AuthMiddleware() gin.HandlerFunc.
  5. models/

    • Contains structs mapping to database tables (e.g., User with ID, Name, Email...).
    • If using GORM, add the appropriate tags (gorm:"...").
  6. routes/

    • Contains a SetupRouter() function to group and register routes, apply middleware, etc.

    • Example:

      package routes
      
      import (
        "github.com/gin-gonic/gin"
        "my-gin-app/controllers"
        "my-gin-app/middlewares"
      )
      
      func SetupRouter() *gin.Engine {
        r := gin.Default()
      
        r.Use(middlewares.LoggerMiddleware())
      
        user := r.Group("/users")
        {
          user.GET("/", controllers.GetUsers)
          user.POST("/", controllers.CreateUser)
        }
        return r
      }
      
  7. services/

    • Contains business logic (e.g., user_service.go for email sending, domain rules, etc.).
    • Your controllers can remain thin, delegating heavier tasks to these service functions.
  8. repository/ (optional)

    • Separates all database interactions (queries) from services, promoting cleaner architecture.
    • In simpler projects, you can skip this folder and keep queries in services.
  9. go.mod / go.sum

    • Standard Go files for dependency management.
  10. (Additional directories)

    • migrations/ (if using Goose or GORM migrations).
    • test/ (unit or integration tests).
    • docs/ (API documentation, Swagger, etc.).
    • scripts/ (CI/CD scripts).

Mini Example

cmd/server/main.go

package main

import (
    "log"

    "my-gin-app/config"
    "my-gin-app/routes"
)

func main() {
    // 1. Initialize config, DB, etc.
    config.InitConfig()

    // 2. Set up Gin router
    r := routes.SetupRouter()

    // 3. Run
    if err := r.Run(":8080"); err != nil {
        log.Fatal(err)
    }
}

config/config.go

package config

import (
    "fmt"
    "os"
    // import "github.com/joho/godotenv" if you need to load .env
    // import GORM libraries if you plan to connect to a DB
)

func InitConfig() {
    // For example: load environment variables
    // godotenv.Load()

    fmt.Println("Config loaded, database connected... (placeholder)")
}

models/user.go

package models

import "time"

type User struct {
    ID        uint      `gorm:"primaryKey"`
    Name      string    `gorm:"size:255"`
    Email     string    `gorm:"size:255;unique"`
    CreatedAt time.Time
    UpdatedAt time.Time
}

controllers/user_controller.go

package controllers

import (
    "net/http"

    "github.com/gin-gonic/gin"
    "my-gin-app/services"
)

func GetUsers(c *gin.Context) {
    users, err := services.GetAllUsers()
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }
    c.JSON(http.StatusOK, users)
}

func CreateUser(c *gin.Context) {
    var input struct {
        Name  string `json:"name"`
        Email string `json:"email"`
    }
    if err := c.ShouldBindJSON(&input); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    user, err := services.CreateUser(input.Name, input.Email)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }
    c.JSON(http.StatusOK, user)
}

services/user_service.go

package services

import (
    "fmt"
    "my-gin-app/models"
)

// Mocked data for illustration
func GetAllUsers() ([]models.User, error) {
    return []models.User{
        {ID: 1, Name: "Alice", Email: "[email protected]"},
        {ID: 2, Name: "Bob", Email: "[email protected]"},
    }, nil
}

func CreateUser(name, email string) (models.User, error) {
    if email == "" {
        return models.User{}, fmt.Errorf("email is required")
    }
    // Suppose we insert into DB and return the created record
    user := models.User{
        ID:    3,
        Name:  name,
        Email: email,
    }
    return user, nil
}

routes/router.go

package routes

import (
    "github.com/gin-gonic/gin"
    "my-gin-app/controllers"
)

func SetupRouter() *gin.Engine {
    r := gin.Default()

    userGroup := r.Group("/users")
    {
        userGroup.GET("/", controllers.GetUsers)
        userGroup.POST("/", controllers.CreateUser)
    }

    return r
}

Conclusion

  • Gin does not provide a default or strict folder structure. Instead, it trusts developers to organize the project.
  • For mid- to large-sized projects, many people separate controllers, services, models, routes, middlewares, etc., to keep the codebase maintainable.
  • The example above is a commonly used pattern in the Go community:
    1. cmd/server/: main entry point
    2. config/: app configurations (env, DB)
    3. controllers/ (or handlers/): handling HTTP requests
    4. services/: business/domain logic
    5. models/: database schemas (e.g., with GORM)
    6. routes/: routing setup
    7. middlewares/: shared logic for requests (JWT, logging, etc.)
    8. repository/: optional layer for DB queries
    9. go.mod/go.sum: module dependencies

Feel free to modify this structure according to your team’s needs and project size.

Thursday, 9 January 2025

Containerization of PHP and Nginx

Containerization of PHP and Nginx [2025]

Containerizing PHP and Nginx involves creating Docker containers for each service and configuring them to work together seamlessly. This approach ensures consistency across different environments, simplifies deployment, and enhances scalability. Below are the detailed steps to create a basic Docker configuration for PHP and Nginx, based on a simple PHP application.

Table of Contents

  1. Create the Project Structure
  2. Create a PHP Application
  3. Configure Nginx
  4. Create Dockerfile for PHP
  5. Create Dockerfile for Nginx
  6. Create docker-compose.yml
  7. Build and Run the Containers
  8. Verify the Setup
  9. Additional Considerations
  10. Conclusion

1. Create the Project Structure

Start by setting up your project with the following structure:

project
├── index.php
├── nginx
│   └── nginx.conf
├── Dockerfile
├── Dockerfile-nginx
└── docker-compose.yml

This structure organizes your PHP application, Nginx configuration, Dockerfiles, and Docker Compose file in a clear and maintainable manner.

2. Create a PHP Application

Create a simple PHP application to serve as the basis for containerization. In the root of your project (./index.php), add the following code:

<?php
  echo "Hello!";
?>

This basic script will help you verify that your container setup is working correctly.

3. Configure Nginx

Create an Nginx configuration file in nginx/nginx.conf with the following content:

server {
    listen 80;
    server_name localhost;

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

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
    }
}

Explanation:

  • listen 80;: Nginx listens on port 80 for incoming HTTP requests.
  • server_name localhost;: Defines the server name.
  • root /var/www/html;: Sets the root directory for the server.
  • index index.php index.html;: Specifies the index files.
  • location /: Handles requests to the root URL, trying to serve the requested file or returning a 404 error if not found.
  • location ~ .php$: Processes PHP files using PHP-FPM running in the php container on port 9000.

4. Create Dockerfile for PHP

Create a Dockerfile in the root of your project to set up the PHP environment:

# Use the official PHP image with PHP-FPM
FROM php:8.1-fpm

# Set working directory
WORKDIR /var/www/html

# Install necessary PHP extensions
RUN docker-php-ext-install mysqli pdo pdo_mysql

# Copy application files
COPY . /var/www/html

# Set permissions
RUN chown -R www-data:www-data /var/www/html

# Expose port 9000
EXPOSE 9000

# Start PHP-FPM server
CMD ["php-fpm"]

Explanation:

  • FROM php:8.1-fpm: Uses the official PHP image with PHP-FPM.
  • WORKDIR /var/www/html: Sets the working directory inside the container.
  • RUN docker-php-ext-install mysqli pdo pdo_mysql: Installs necessary PHP extensions.
  • COPY . /var/www/html: Copies the application code into the container.
  • RUN chown -R www-data:www-data /var/www/html: Sets appropriate permissions.
  • EXPOSE 9000: Exposes port 9000 for communication with Nginx.
  • CMD ["php-fpm"]: Starts the PHP-FPM server.

5. Create Dockerfile for Nginx

Create a Dockerfile-nginx in the nginx directory to set up the Nginx environment:

# Use the official Nginx image
FROM nginx:latest

# Remove the default Nginx configuration
RUN rm /etc/nginx/conf.d/default.conf

# Copy the custom Nginx configuration
COPY nginx.conf /etc/nginx/conf.d

# Copy application files to serve static content if needed
COPY ../ /var/www/html

# Expose port 80
EXPOSE 80

# Start Nginx
CMD ["nginx", "-g", "daemon off;"]

Explanation:

  • FROM nginx:latest: Uses the latest official Nginx image.
  • RUN rm /etc/nginx/conf.d/default.conf: Removes the default Nginx configuration.
  • COPY nginx.conf /etc/nginx/conf.d: Copies your custom Nginx configuration.
  • COPY ../ /var/www/html: Copies application files for serving static content.
  • EXPOSE 80: Exposes port 80 for HTTP traffic.
  • CMD ["nginx", "-g", "daemon off;"]: Starts Nginx in the foreground.

6. Create docker-compose.yml

Create a docker-compose.yml file in the root of your project to orchestrate the PHP and Nginx containers:

version: '3.8'

services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/var/www/html
    networks:
      - app-network

  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile-nginx
    ports:
      - "80:80"
    depends_on:
      - php
    volumes:
      - .:/var/www/html
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

Explanation:

  • version: '3.8': Specifies the Docker Compose version.
  • services: Defines the services (php and nginx).
    • php:
      • build: Builds the PHP container using the specified Dockerfile.
      • volumes: Mounts the current directory to /var/www/html inside the container.
      • networks: Connects to the app-network.
    • nginx:
      • build: Builds the Nginx container using the specified Dockerfile.
      • ports: Maps port 80 of the host to port 80 of the container.
      • depends_on: Ensures Nginx starts after PHP.
      • volumes: Mounts the current directory to /var/www/html inside the container.
      • networks: Connects to the app-network.
  • networks:
    • app-network: Defines a bridge network for inter-service communication.

7. Build and Run the Containers

Navigate to the root of your project in the terminal and execute the following command to build and start the containers:

docker-compose up -d --build
  • -d: Runs the containers in detached mode.
  • --build: Forces a rebuild of the Docker images.

Expected Output:

Creating network "project_app-network" with the default driver
Building php
Step 1/7 : FROM php:8.1-fpm
...
Successfully built abc123def456
Successfully tagged project_php:latest
Building nginx
Step 1/5 : FROM nginx:latest
...
Successfully built ghi789jkl012
Successfully tagged project_nginx:latest
Creating project_php_1    ... done
Creating project_nginx_1 ... done

8. Verify the Setup

After the containers are up and running, open your web browser and navigate to http://localhost. You should see the message:

Hello!

This confirms that Nginx is correctly serving the PHP application through the Docker containers.

Troubleshooting Tips

  • Port Conflicts: Ensure that port 80 is not being used by another service on your host machine.

  • Container Logs: If you encounter issues, check the logs using:

    docker-compose logs
    
  • Container Status: Verify that all containers are running using:

    docker-compose ps
    

9. Additional Considerations

While the above setup provides a basic containerization of PHP and Nginx, consider the following enhancements for more complex applications:

Environment Variables

Manage configuration settings using environment variables. You can define them in the docker-compose.yml file under each service or use a .env file for better security and flexibility.

services:
  php:
    environment:
      - APP_ENV=production
      - DB_HOST=db
  nginx:
    environment:
      - NGINX_HOST=localhost

Database Integration

If your PHP application requires a database, add another service (e.g., MySQL or PostgreSQL) to the docker-compose.yml and configure PHP to connect to it.

services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: app_password
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - app-network

volumes:
  db_data:

Update the php service to include the database connection details.

Persistent Storage

Ensure that any data you want to persist (like database files) is stored in Docker volumes to prevent data loss when containers are recreated.

Scaling Services

Docker Compose allows you to scale services. For example, you can run multiple instances of the PHP service to handle increased load:

docker-compose up --scale php=3 -d

Security

  • Update Docker Images: Always keep your Docker images updated to include the latest security patches.

  • Multi-Stage Builds: Use multi-stage builds to minimize the image size and reduce the attack surface.

    FROM node:14 AS build
    WORKDIR /app
    COPY . .
    RUN npm install && npm run build
    
    FROM nginx:alpine
    COPY --from=build /app/build /usr/share/nginx/html
    
  • User Permissions: Run containers with non-root users where possible to enhance security.

Logging and Monitoring

Implement logging and monitoring solutions to track the performance and health of your containers. Tools like Prometheus, Grafana, and ELK Stack can be integrated for comprehensive monitoring.

10. Conclusion

Containerizing PHP and Nginx using Docker simplifies the deployment process, ensures consistency across different environments, and enhances scalability. By following the steps outlined above, you can set up a robust environment for your PHP applications, making development and deployment more efficient and manageable.

Embracing containerization not only streamlines your workflow but also positions your applications for better performance and reliability in production environments. As you grow your applications, consider integrating more advanced Docker features and orchestration tools like Kubernetes to further optimize your infrastructure.


Happy Coding!

Feel free to follow me for more insights on containerization, Docker, and web development best practices.

Wednesday, 8 January 2025

Laravel Project structure combines SOLID principles and Design patterns in Laravel

I. SOLID principles

1. Single Responsibility Principle (SRP)

Adopt a modular structure that respects SRP (Single Responsibility Principle) and facilitates the use of design patterns:

app/ ├── Actions/ # For Single Action Classes ├── Contracts/ # For Interfaces ├── DTOs/ # For Data Transfer Objects ├── Events/ # For Events ├── Exceptions/ # For Custom Exceptions ├── Http/ │ ├── Controllers/ # REST/GraphQL Controllers │ ├── Middleware/ # Middleware Classes │ ├── Requests/ # Form Request Validation ├── Jobs/ # For Jobs and Commands ├── Listeners/ # For Event Listeners ├── Models/ # Eloquent Models ├── Observers/ # For Model Observers ├── Policies/ # For Authorization Logic ├── Providers/ # Service Providers ├── Repositories/ # Repository Pattern ├── Rules/ # Custom Validation Rules ├── Services/ # Service Layer for Business Logic └── ViewModels/ # For View Model Logic

2. Open/Closed Principle (OCP)

  • Use Strategy Pattern to extend functionality without modifying existing code.

3. Liskov Substitution Principle (LSP)

  • Rely on abstractions (Contracts), and ensure derived classes are substitutable.

4. Interface Segregation Principle (ISP)

  • Use smaller, specific interfaces (e.g., UserRepositoryInterface, PostRepositoryInterface).

5. Dependency Inversion Principle (DIP)

  • Inject dependencies using Laravel's Service Container.
II. Essential Design Patterns in Laravel

1. Repository Pattern

  • Create repositories for data access:
    • Example: UserRepository for interacting with user data.
    namespace App\Repositories; use App\Models\User; class UserRepository implements UserRepositoryInterface { public function findById($id) { return User::find($id); } }

2. Service Pattern

  • Move business logic to services:
    namespace App\Services; use App\Repositories\UserRepositoryInterface; class UserService { protected $userRepository; public function __construct(UserRepositoryInterface $userRepository) { $this->userRepository = $userRepository; } public function getUserProfile($id) { return $this->userRepository->findById($id); } }

3 Factory Pattern

  • Use Laravel's built-in factories for generating test data:
    User::factory()->create();

4. Strategy Pattern

  • Implement strategies for interchangeable algorithms:
    namespace App\Services\Payment; interface PaymentStrategy { public function pay($amount); } class PaypalPayment implements PaymentStrategy { public function pay($amount) { // Pay with PayPal } } class CreditCardPayment implements PaymentStrategy { public function pay($amount) { // Pay with Credit Card } }

5 Observer Pattern

  • Use model observers for handling model events:
    namespace App\Observers; use App\Models\User; class UserObserver { public function created(User $user) { // Send welcome email } }

6 Decorator Pattern

  • Extend existing functionalities dynamically:
    namespace App\Services; class LoggerDecorator { protected $service; public function __construct($service) { $this->service = $service; } public function execute() { \Log::info('Executing service'); return $this->service->execute(); } }

7 Builder Pattern

  • Chain complex object creation:
    namespace App\Builders; class UserQueryBuilder { protected $query; public function __construct() { $this->query = User::query(); } public function whereActive() { $this->query->where('active', true); return $this; } public function whereRole($role) { $this->query->where('role', $role); return $this; } public function get() { return $this->query->get(); } }
Thank you

Tuesday, 7 January 2025

Puppeteer with Chromium or the full Chrome browser

 When deciding whether to use Puppeteer with Chromium or the full Chrome browser, it depends on your specific requirements. Here's a breakdown to help you decide:


1. Puppeteer with Chromium (Default)

Advantages:

  • Optimized for Puppeteer: Puppeteer ships with Chromium, which is guaranteed to work seamlessly with it. Any Puppeteer API updates will be directly compatible with the bundled Chromium version.
  • Lightweight and Fast: Chromium is a lighter version of Chrome, making it faster and consuming fewer resources.
  • No Dependencies: By using the bundled Chromium, you avoid compatibility issues between Puppeteer and other Chrome versions installed on your machine.
  • Easier for Automation: Ideal for running headless browsers in CI/CD pipelines or lightweight environments like Docker.

Disadvantages:

  • Outdated Features: Chromium bundled with Puppeteer might not have the latest Chrome features or updates.
  • Missing Full Chrome Functionality: Some DRM-protected content or proprietary features exclusive to the full Chrome browser may not work.

2. Puppeteer with Full Chrome Browser

Advantages:

  • Access to Latest Features: If you need the latest updates, security patches, or features from Chrome, this is a better choice.
  • Wide Compatibility: Full Chrome ensures you can replicate user environments as accurately as possible, especially for browser-specific testing.
  • Supports Proprietary Features: For tasks requiring proprietary codecs (e.g., H.264, MP3), the full Chrome browser is better since Chromium doesn't always support them.

Disadvantages:

  • Requires Extra Configuration: You'll need to ensure Puppeteer works with your installed Chrome version, which may involve additional configuration (e.g., passing the path to Chrome in Puppeteer).
  • Heavier Resource Usage: Full Chrome is heavier and may consume more memory and processing power compared to Chromium.

When to Choose Which:

Use CaseRecommendation
General web scraping or testingPuppeteer with Chromium
CI/CD environments or DockerPuppeteer with Chromium
Mimicking real user environmentsPuppeteer with full Chrome
DRM-protected content or media appsPuppeteer with full Chrome
Lightweight environment (Alpine)Puppeteer with Chromium

Key Notes:

  • To use Puppeteer with full Chrome, you'll need to specify the Chrome binary path:
    javascript
    const puppeteer = require('puppeteer'); puppeteer.launch({ executablePath: '/path/to/chrome', });
  • Keep in mind that Puppeteer works best with its bundled Chromium and may require extra debugging when used with other browser versions.

If you’re running in production or CI/CD environments, Puppeteer with Chromium is usually sufficient. However, for scenarios that require real-world testing or proprietary features, consider switching to full Chrome.

Monday, 6 January 2025

Nginx configuration with explanations

 Nginx configuration with explanations for various keywords and directives you will encounter in a typical Nginx setup:

1. Basic Nginx Configuration File Structure

The main configuration file for Nginx is usually located at /etc/nginx/nginx.conf.

user nginx; worker_processes auto; pid /run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; server { listen 80; server_name example.com www.example.com; location / { root /usr/share/nginx/html; index index.html index.htm; } } }

2. Global Directives

  • user: Specifies the user and group under which Nginx workers will run.
  • worker_processes: The number of worker processes that Nginx will spawn. auto will set this to the number of CPU cores.
  • pid: The file location where Nginx stores its process ID.

3. Events Block

The events block defines settings that affect the operation of worker processes.

  • worker_connections: Specifies the maximum number of simultaneous connections each worker process can handle.
events { worker_connections 1024; }

4. HTTP Block

The http block contains directives that configure the HTTP server functionality. This is where you define most of your server configurations.

  • include: Includes other configuration files (e.g., MIME types).
  • default_type: Specifies the default MIME type if it cannot be determined.
http { include /etc/nginx/mime.types; default_type application/octet-stream; }

5. Server Block

Each server block defines a virtual server.

  • listen: Specifies the port and/or IP address to listen on (e.g., listen 80;).
  • server_name: Defines the domain names or IP addresses the server will respond to.
  • location: Defines how to handle requests for specific URI patterns.
server { listen 80; server_name example.com www.example.com; location / { root /usr/share/nginx/html; index index.html index.htm; } }

6. Location Block

The location block is used to define how to handle specific URI patterns or locations.

  • root: Specifies the directory from which files will be served.
  • index: Specifies the index file to serve when a directory is requested.
  • try_files: Tries to serve the file and, if not found, can redirect to another location.

Example:

location / { root /var/www/html; index index.php index.html index.htm; }

7. Rewrite and Redirects

  • rewrite: This directive allows you to rewrite URLs based on regular expressions.
  • return: This is used to send an HTTP response directly, often for redirects.

Example:

rewrite ^/old-page$ /new-page permanent; return 301 https://example.com$request_uri;

8. SSL Configuration

To serve HTTPS traffic, you’ll need to include SSL certificates and enable SSL in your server block.

server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/ssl/example.crt; ssl_certificate_key /etc/nginx/ssl/example.key; location / { root /usr/share/nginx/html; index index.html; } }

9. Proxy and Reverse Proxy Configuration

You can use Nginx as a reverse proxy to forward traffic to an upstream server.

server { listen 80; server_name example.com; location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }

10. Error Handling

You can define custom error pages for certain HTTP status codes.

server { listen 80; server_name example.com; error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; } }

11. Gzip Compression

Enabling Gzip can improve your website's performance by compressing responses.

http { gzip on; gzip_types text/plain text/css application/javascript application/json application/xml text/javascript; gzip_min_length 1000; }

12. Caching

You can configure caching rules for certain resources.

location ~* \.(jpg|jpeg|png|gif|css|js)$ { expires 30d; add_header Cache-Control "public, no-transform"; }

13. Access Control

  • allow: Grants access to a specific IP address or range.
  • deny: Denies access to a specific IP address or range.

Example:

location /admin { allow 192.168.1.1; deny all; }

14. Logging

You can configure logging for access and errors.

http { access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; }

15. Load Balancing

To load balance requests across multiple servers, use the upstream directive.

upstream backend { server backend1.example.com; server backend2.example.com; } server { location / { proxy_pass http://backend; } }

16. Rate Limiting

Rate limiting is used to control the number of requests a client can make in a given period.

http { limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s; server { location / { limit_req zone=mylimit burst=5; } } }

Conclusion

This is a general overview of the essential Nginx configuration keywords and directives. You can use these directives to set up a basic to advanced Nginx configuration for serving static files, reverse proxying, SSL setup, caching, logging, error handling, and more. Be sure to consult the official Nginx documentation for more detailed information on any specific directive.

Summary

File/DirectoryPurpose
/etc/nginx/nginx.confMain Nginx configuration file.
/etc/nginx/sites-available/Virtual host configuration files.
/etc/nginx/sites-enabled/Symlinks to enabled virtual host configurations.
/etc/nginx/mime.typesMaps file extensions to MIME types.
/etc/nginx/conf.d/Additional configuration files (e.g., SSL).
/etc/nginx/snippets/Reusable configuration snippets.
/var/log/nginx/Stores access and error logs.
/etc/nginx/ssl/Stores SSL certificates and keys.

Thank you.

Publish npm package

  Để publish   pav-kit  lên NPM, bạn hãy làm theo các bước dưới đây. Tôi đã tạo thêm file  index.js  để đảm bảo gói tin hợp lệ. Bước 1: Tạo ...