### Establish Connection and Subscribe (Go Example) Source: https://context7.com/nginx/agent/llms.txt Example demonstrating how to establish a connection and subscribe to commands using the generated Go client. ```APIDOC ## Establish Connection and Subscribe (Go Example) This example shows how to use the generated Go client to interact with the `CommandService`. ### 1. CreateConnection Establishes a connection with the management plane. ```go conn, _ := grpc.NewClient("agent.connect.nginx.com:443", grpc.WithTransportCredentials(creds)) client := mpi.NewCommandServiceClient(conn) resp, err := client.CreateConnection(ctx, &mpi.CreateConnectionRequest{ MessageMeta: &mpi.MessageMeta{ MessageId: id.GenerateMessageID(), CorrelationId: id.GenerateMessageID(), Timestamp: timestamppb.Now(), }, Resource: &mpi.Resource{ ResourceId: "550e8400-e29b-41d4-a716-446655440000", Instances: []*mpi.Instance{ { InstanceMeta: &mpi.InstanceMeta{ InstanceId: "7c9e6679-7425-40de-944b-e07fc1f90ae7", InstanceType: mpi.InstanceMeta_INSTANCE_TYPE_NGINX, Version: "1.27.0", }, InstanceRuntime: &mpi.InstanceRuntime{ ProcessId: 1234, BinaryPath: "/usr/sbin/nginx", ConfigPath: "/etc/nginx/nginx.conf", Details: &mpi.InstanceRuntime_NginxRuntimeInfo{ NginxRuntimeInfo: &mpi.NGINXRuntimeInfo{ StubStatus: &mpi.APIDetails{Listen: "127.0.0.1:8080", Location: "/stub_status"}, AccessLogs: []string{"/var/log/nginx/access.log"}, ErrorLogs: []string{"/var/log/nginx/error.log"}, }, }, }, }, }, Info: &mpi.Resource_HostInfo{ HostInfo: &mpi.HostInfo{ HostId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", Hostname: "web-01.example.com", ReleaseInfo: &mpi.ReleaseInfo{ Id: "ubuntu", Name: "Ubuntu", Version: "22.04", }, }, }, }, }) if err != nil { log.Fatal(err) } // resp.Response.Status == mpi.CommandResponse_COMMAND_STATUS_OK // resp.AgentConfig contains MP-recommended agent configuration ``` ### 2. Subscribe Initiates a bidirectional stream for receiving commands and sending responses. ```go stream, _ := client.Subscribe(ctx) // Send a DataPlaneResponse to acknowledge or report _ = stream.Send(&mpi.DataPlaneResponse{ MessageMeta: &mpi.MessageMeta{MessageId: id.GenerateMessageID(), Timestamp: timestamppb.Now()}, CommandResponse: &mpi.CommandResponse{Status: mpi.CommandResponse_COMMAND_STATUS_OK, Message: "ready"}, RequestType: mpi.DataPlaneResponse_HEALTH_REQUEST, }) // Receive a ManagementPlaneRequest from the MP req, _ := stream.Recv() switch req.GetRequest().(type) { case *mpi.ManagementPlaneRequest_ConfigApplyRequest: // handle config apply case *mpi.ManagementPlaneRequest_HealthRequest: // respond with health data case *mpi.ManagementPlaneRequest_UpdateAgentConfigRequest: // update agent config dynamically } ``` ``` -------------------------------- ### Install SELinux Development Tools Source: https://github.com/nginx/agent/blob/main/scripts/selinux/README.md Installs necessary development tools for SELinux policy management. ```bash sudo yum install policycoreutils-devel rpm-build ``` -------------------------------- ### Install SELinux Policy Package Source: https://github.com/nginx/agent/blob/main/scripts/selinux/README.md Use this command to install a SELinux policy package. Ensure you have the correct path to the .pp file. ```bash sudo semodule -n -i /usr/share/selinux/packages/nginx_agent.pp ``` -------------------------------- ### Start Mock Management gRPC Server Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Run this command to start the mock server. It defaults to a random port and saves config to /tmp. ```bash make run-mock-management-grpc-server ``` -------------------------------- ### Start Mock Management OTel Collector Source: https://github.com/nginx/agent/blob/main/test/mock/collector/README.md Starts all services, including the mock management OTel collector and associated NGINX agents. ```bash make run-mock-management-otel-collector ``` -------------------------------- ### Example NGINX Agent Configuration File Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md This is an example configuration file for the NGINX Agent, showing settings for logging, allowed directories, and command server connection. ```yaml # # /etc/nginx-agent/nginx-agent.conf # # Configuration file for NGINX Agent. # log: # set log level (error, warn, info, debug; default "info") level: info # set log path. if empty, don't log to file. path: /var/log/nginx-agent/ allowed_directories: - /etc/nginx - /etc/app_protect - /usr/local/etc/nginx - /usr/share/nginx/modules - /var/run/nginx - /var/log/nginx # # Command server settings to connect to a management plane server # #command: # server: # host: "agent.connect.nginx.com" # port: 443 # auth: # token: "" # tls: # skip_verify: false command: server: host: localhost port: 9091 ``` -------------------------------- ### NGINX Agent Response Example Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Example response structure from the NGINX Agent on the Subscribe RPC stream. ```json [ { "message_meta": { "message_id": "0971692c-c0bf-4b67-a03b-ef13b3c3ea9b", "correlation_id": "87e3c12f-eaf7-4f54-a27c-c91fe75d44a6", "timestamp": { "seconds": 1729862076, "nanos": 98825000 } }, "command_response": { "status": 1, "message": "Successfully updated all files" } } ] ``` -------------------------------- ### Example Response for GET /api/v1/connection Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md This JSON response indicates a successful connection between the NGINX Agent and the management plane. It includes details about the host, NGINX instances, and agent configuration. ```json { "messageMeta": { "correlationId": "0d777e07-bbdf-4ce9-a8d2-22b1e8383984", "messageId": "4300d60e-0e4e-4761-a934-d93623e07b90", "timestamp": "2024-10-25T13:14:36.028654Z" }, "resource": { "hostInfo": { "hostId": "14bb13db-347d-33b4-92f6-0e3d33e0d840", "hostname": "example.com", "releaseInfo": { "codename": "darwin", "id": "darwin", "name": "Standalone Workstation", "version": "23.6.0", "versionId": "14.6.1" } }, "instances": [ { "instanceConfig": { "agentConfig": { "command": {}, "features": [ "configuration", "connection", "metrics", "file-watcher" ], "file": {}, "metrics": {} } }, "instanceMeta": { "instanceId": "9da17ae7-aadc-3dff-8299-fbce82ec0175", "instanceType": "INSTANCE_TYPE_AGENT" }, "instanceRuntime": { "binaryPath": "/var/usr/bin/nginx-agent", "configPath": "/etc/nginx-agent/nginx-agent.conf", "processId": 31877 } }, { "instanceMeta": { "instanceId": "6cb1a2bc-7552-33b1-9e7c-cb6658b82ebb", "instanceType": "INSTANCE_TYPE_NGINX", "version": "1.27.0" }, "instanceRuntime": { "binaryPath": "/usr/local/bin/nginx", "configPath": "/usr/local/etc/nginx/nginx.conf", "instanceChildren": [ { "processId": 703 } ], "nginxRuntimeInfo": { "accessLogs": [ "/usr/local/var/log/nginx/access.log" ], "dynamicModules": [ "http_addition_module", "http_auth_request_module", "http_dav_module", "http_degradation_module", "http_flv_module", "http_gunzip_module", "http_gzip_static_module", "http_mp4_module", "http_random_index_module", "http_realip_module", "http_secure_link_module", "http_slice_module", "http_ssl_module", "http_stub_status_module", "http_sub_module", "http_v2_module", "http_v3_module", "mail_ssl_module", "stream_realip_module", "stream_ssl_module", "stream_ssl_preread_module" ], "errorLogs": [ "/usr/local/var/log/nginx/error.log" ], "stubStatus": "http://127.0.0.1:8084/apitesst" }, "processId": 595 } } ], "resourceId": "14bb13db-347d-33b4-92f6-0e3d33e0d840" } } ``` -------------------------------- ### NGINX Agent Get Upstreams Request Example Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Example request body to retrieve upstream information from the NGINX Agent. ```json { "message_meta": { "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", "timestamp": "2023-01-15T01:30:15.01Z" }, "action_request": { "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", "nginx_plus_action": { "get_upstreams": {} } } } ``` -------------------------------- ### Establish Connection and Subscribe with Go Client Source: https://context7.com/nginx/agent/llms.txt Example of using the generated Go client to establish a connection and subscribe to commands via the CommandService. Ensure proper gRPC credentials and context are handled. ```go // Example: establish connection and subscribe using the generated Go client import ( mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1" "github.com/nginx/agent/v3/pkg/id" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/timestamppb" ) conn, _ := grpc.NewClient("agent.connect.nginx.com:443", grpc.WithTransportCredentials(creds)) client := mpi.NewCommandServiceClient(conn) // 1. CreateConnection — registers the agent/resource with the management plane resp, err := client.CreateConnection(ctx, &mpi.CreateConnectionRequest{ MessageMeta: &mpi.MessageMeta{ MessageId: id.GenerateMessageID(), CorrelationId: id.GenerateMessageID(), Timestamp: timestamppb.Now(), }, Resource: &mpi.Resource{ ResourceId: "550e8400-e29b-41d4-a716-446655440000", Instances: []*mpi.Instance{ { InstanceMeta: &mpi.InstanceMeta{ InstanceId: "7c9e6679-7425-40de-944b-e07fc1f90ae7", InstanceType: mpi.InstanceMeta_INSTANCE_TYPE_NGINX, Version: "1.27.0", }, InstanceRuntime: &mpi.InstanceRuntime{ ProcessId: 1234, BinaryPath: "/usr/sbin/nginx", ConfigPath: "/etc/nginx/nginx.conf", Details: &mpi.InstanceRuntime_NginxRuntimeInfo{ NginxRuntimeInfo: &mpi.NGINXRuntimeInfo{ StubStatus: &mpi.APIDetails{Listen: "127.0.0.1:8080", Location: "/stub_status"}, AccessLogs: []string{"/var/log/nginx/access.log"}, ErrorLogs: []string{"/var/log/nginx/error.log"}, }, }, }, }, }, Info: &mpi.Resource_HostInfo{ HostInfo: &mpi.HostInfo{ HostId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890", Hostname: "web-01.example.com", ReleaseInfo: &mpi.ReleaseInfo{ Id: "ubuntu", Name: "Ubuntu", Version: "22.04", }, }, }, }, }) if err != nil { log.Fatal(err) } // resp.Response.Status == mpi.CommandResponse_COMMAND_STATUS_OK // resp.AgentConfig contains MP-recommended agent configuration // 2. Subscribe — bidirectional stream for receiving commands stream, _ := client.Subscribe(ctx) // Send a DataPlaneResponse to acknowledge or report _ = stream.Send(&mpi.DataPlaneResponse{ MessageMeta: &mpi.MessageMeta{MessageId: id.GenerateMessageID(), Timestamp: timestamppb.Now()}, CommandResponse: &mpi.CommandResponse{Status: mpi.CommandResponse_COMMAND_STATUS_OK, Message: "ready"}, RequestType: mpi.DataPlaneResponse_HEALTH_REQUEST, }) // Receive a ManagementPlaneRequest from the MP req, _ := stream.Recv() switch req.GetRequest().(type) { case *mpi.ManagementPlaneRequest_ConfigApplyRequest: // handle config apply case *mpi.ManagementPlaneRequest_HealthRequest: // respond with health data case *mpi.ManagementPlaneRequest_UpdateAgentConfigRequest: // update agent config dynamically } ``` -------------------------------- ### Start Mock OTel Collector Without NAP Source: https://github.com/nginx/agent/blob/main/test/mock/collector/README.md Starts all services except for the NGINX Plus & NGINX App Protect agent. ```bash make run-mock-otel-collector-without-nap ``` -------------------------------- ### NGINX Agent Get Stream Upstreams Request Example Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Example request body to retrieve stream upstream information from the NGINX Agent. ```json { "message_meta": { "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", "timestamp": "2023-01-15T01:30:15.01Z" }, "action_request": { "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", "nginx_plus_action": { "get_stream_upstreams": {} } } } ``` -------------------------------- ### Install NGINX Agent SELinux Policy Source: https://github.com/nginx/agent/blob/main/scripts/selinux/README.md Installs the SELinux policy package for the NGINX Agent and applies security contexts. ```bash sudo semodule -n -i /usr/share/selinux/packages/nginx_agent.pp ``` ```bash sudo /usr/sbin/load_policy ``` ```bash sudo restorecon -R /usr/bin/nginx-agent ``` ```bash sudo restorecon -R /var/log/nginx-agent ``` ```bash sudo restorecon -R /etc/nginx-agent ``` -------------------------------- ### NGINX Agent Get HTTP Upstream Servers Request Example Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Example request body to retrieve HTTP upstream server information from the NGINX Agent. ```json { "message_meta": { "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", "timestamp": "2023-01-15T01:30:15.01Z" }, "action_request": { "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", "nginx_plus_action": { "get_http_upstream_servers": { "http_upstream_name": "nginx1" } } } } ``` -------------------------------- ### Interact with FileService gRPC API in Go Source: https://context7.com/nginx/agent/llms.txt Demonstrates how to use the FileServiceClient in Go to get file overviews, retrieve file content, update files, and stream large files. ```go import ( mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1" "github.com/nginx/agent/v3/pkg/id" "google.golang.org/protobuf/types/known/timestamppb" ) fileClient := mpi.NewFileServiceClient(conn) msgMeta := &mpi.MessageMeta{MessageId: id.GenerateMessageID(), Timestamp: timestamppb.Now()} // Get the file overview for a config version overviewResp, err := fileClient.GetOverview(ctx, &mpi.GetOverviewRequest{ MessageMeta: msgMeta, ConfigVersion: &mpi.ConfigVersion{ InstanceId: "7c9e6679-7425-40de-944b-e07fc1f90ae7", Version: "abc123", }, }) // overviewResp.Overview.Files → []*mpi.File // Get a single file's content fileResp, err := fileClient.GetFile(ctx, &mpi.GetFileRequest{ MessageMeta: msgMeta, FileMeta: &mpi.FileMeta{Name: "/etc/nginx/nginx.conf", Hash: "abc123..."}, }) nginxConf := fileResp.Contents.Contents // []byte // Update a file (push from agent to MP) updateResp, err := fileClient.UpdateFile(ctx, &mpi.UpdateFileRequest{ MessageMeta: msgMeta, File: &mpi.File{ FileMeta: &mpi.FileMeta{ Name: "/etc/nginx/nginx.conf", Hash: "sha256ofcontents", Permissions: "0644", Size: 1024, }, }, Contents: &mpi.FileContents{Contents: []byte("worker_processes auto;\n...")}, }) // updateResp.FileMeta.Hash confirms the upload // Stream a large file using pkg/files helpers import "github.com/nginx/agent/v3/pkg/files" stream, _ := fileClient.GetFileStream(ctx, &mpi.GetFileRequest{ MessageMeta: msgMeta, FileMeta: &mpi.FileMeta{Name: "/etc/nginx/large.conf"}, }) var buf bytes.Buffer header, err := files.RecvChunkedFile(stream, &buf) // header.Name, header.Hash, header.Size describe the received file // buf.Bytes() contains the full file content ``` -------------------------------- ### Configure Container Metrics Receiver Source: https://github.com/nginx/agent/blob/main/internal/collector/containermetricsreceiver/README.md Example configuration for the containermetrics receiver, showing optional settings for collection interval and initial delay. ```yaml containermetrics: collection_interval: # default = 1m initial_delay: # default = 1s ``` -------------------------------- ### NGINX Agent Update Stream Servers Request Example Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Example request body to update stream server configuration on the NGINX Agent. ```json { "message_meta": { "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", "timestamp": "2023-01-15T01:30:15.01Z" }, "action_request": { "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", "nginx_plus_action": { "update_stream_servers": { "upstream_stream_name": "stream_backend", "servers": [ { "id" : 0, "server" : "10.0.0.1:12348", "weight" : 1, "max_conns" : 0, "max_fails" : 1, "fail_timeout" : "10s", "slow_start" : 0, "backup" : false, "down" : false } ] } } } } ``` -------------------------------- ### NGINX Agent Configuration File Example Source: https://context7.com/nginx/agent/llms.txt This YAML configuration file defines settings for the NGINX Agent, including logging, allowed directories for NGINX configuration management, feature flags, primary and auxiliary command server details, gRPC client tuning, and OpenTelemetry Collector configuration. ```yaml # /etc/nginx-agent/nginx-agent.conf log: level: info # error | warn | info | debug path: /var/log/nginx-agent/ # Directories the agent is allowed to read/write for NGINX config management allowed_directories: - /etc/nginx - /etc/app_protect - /usr/local/etc/nginx - /usr/share/nginx/modules - /var/run/nginx - /var/log/nginx # Feature flags (defaults shown; all are on unless noted) features: - configuration - certificates - metrics - file-watcher - logs-nap # Command server: the gRPC Management Plane endpoint command: server: host: "agent.connect.nginx.com" port: 443 type: grpc # grpc | http auth: token: "my-api-token" token_path: "/etc/nginx-agent/token" # or file-based token tls: cert: "/etc/nginx-agent/client.pem" key: "/etc/nginx-agent/client.key" ca: "/etc/nginx-agent/ca.pem" skip_verify: false server_name: "agent.connect.nginx.com" server: proxy: url: "http://proxy.example.com:3128" auth_method: "basic" username: "proxyuser" password: "proxypass" # Optional second read-only management plane connection auxiliary_command: server: host: "audit.nginx.com" port: 443 # gRPC client tuning client: grpc: max_message_receive_size: 4194304 # 4 MB (default) max_message_send_size: 4194304 keep_alive: time: 20s timeout: 10s permit_without_stream: true # OTel Collector for metrics/logs export collector: receivers: host_metrics: collection_interval: 1m exporters: otlp_exporters: - server: host: "otel-collector.example.com" port: 4317 tls: skip_verify: false ``` -------------------------------- ### Configure NGINX Receiver Source: https://github.com/nginx/agent/blob/main/internal/collector/nginxreceiver/README.md Example configuration for the NGINX receiver, specifying details for the status endpoint and access logs. ```yaml receivers: nginx: api_details: url: "http://localhost:80/status" listen: "localhost:80" location: "/status" collection_interval: 10s access_logs: - log_format: "$remote_addr - $remote_user [$time_local] \"$request\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" \"$http_x_forwarded_for\"\"$upstream_cache_status\"" file_path: "/var/log/nginx/access-custom.conf" ``` -------------------------------- ### Configure NGINX Plus Receiver Source: https://github.com/nginx/agent/blob/main/internal/collector/nginxplusreceiver/README.md Example configuration for the NGINX Plus receiver, specifying API endpoint details and collection interval. ```yaml receivers: nginxplus: api_details: url: "http://localhost:80/api" listen: "localhost:80" location: "/api" collection_interval: 10s ``` -------------------------------- ### Agent Configuration Block Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Update the agent configuration with this block before starting the NGINX Agent to connect to the mock server. ```yaml command: server: host: localhost port: 9091 ``` -------------------------------- ### Build and Run Mock Management Server Source: https://context7.com/nginx/agent/llms.txt Instructions for building and running the mock management plane server, useful for integration testing and as an implementation reference. ```bash # Build and run the mock management server go run ./test/mock/grpc/cmd/main.go --port=9090 ``` -------------------------------- ### Initialize and Use Command Plugin Source: https://context7.com/nginx/agent/llms.txt Initializes the Command Plugin for handling management plane commands. Ensure gRPC connection and agent configuration are set up. ```go import ( "github.com/nginx/agent/v3/internal/command" "github.com/nginx/agent/v3/internal/grpc" "github.com/nginx/agent/v3/internal/model" ) grpcConn, _ := grpc.NewGrpcConnection(ctx, agentConfig, agentConfig.Command) cmdPlugin := command.NewCommandPlugin(agentConfig, grpcConn, model.Command) // model.Command = primary plane; model.Auxiliary = read-only secondary plane // cmdPlugin.Subscriptions(): // [ConnectionResetTopic, ResourceUpdateTopic, InstanceHealthTopic, // DataPlaneHealthResponseTopic, DataPlaneResponseTopic] // On receiving bus.ResourceUpdateTopic with *mpi.Resource: // → if not connected: calls CommandService.CreateConnection, starts Subscribe goroutine // → if connected: calls CommandService.UpdateDataPlaneStatus // On receiving ManagementPlaneRequest from Subscribe stream: // ConfigUploadRequest → publishes to bus.ConfigUploadRequestTopic // ConfigApplyRequest → publishes to bus.ConfigApplyRequestTopic // HealthRequest → publishes to bus.DataPlaneHealthRequestTopic // ActionRequest → publishes to bus.APIActionRequestTopic (if FeatureAPIAction enabled) // UpdateAgentConfigRequest → publishes to bus.AgentConfigUpdateTopic // Reconfigure live (called by MessagePipe when AgentConfig changes) _ = cmdPlugin.Reconfigure(ctx, updatedAgentConfig) ``` -------------------------------- ### NGINX Agent Health Request Example Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Example request body to send a health check to the NGINX Agent. ```json { "message_meta": { "message_id": "e2254df9-8edd-4900-91ce-88782473bcb9", "correlation_id": "9673f3b4-bf33-4d98-ade1-ded9266f6818", "timestamp": "2023-01-15T01:30:15.01Z" }, "health_request": {} } ``` -------------------------------- ### Initialize and Use MessagePipe Source: https://context7.com/nginx/agent/llms.txt Initializes the in-process event bus (`MessagePipe`) and demonstrates publishing messages. Ensure `ctx` is a valid context and `agentConfig` and `myPlugins` are properly initialized. ```go import ( "github.com/nginx/agent/v3/internal/bus" "github.com/nginx/agent/v3/internal/config" ) agentConfig := &config.Config{} pipe := bus.NewMessagePipe(256, agentConfig) // Register plugins (each plugin.Subscriptions() lists its topics) _ = pipe.Register(256, myPlugins) // Publish a message — any subscribed plugin will receive it pipe.Process(ctx, &bus.Message{Topic: bus.ResourceUpdateTopic, Data: myResource}, &bus.Message{Topic: bus.InstanceHealthTopic, Data: myHealthSlice}, ) // Standard bus topics (bus/topics.go): // bus.ConnectionResetTopic — gRPC reconnection event // bus.ResourceUpdateTopic — NGINX instance resource changed // bus.InstanceHealthTopic — instance health changed // bus.DataPlaneHealthResponseTopic — health response ready to send // bus.DataPlaneResponseTopic — command response ready to send // bus.ConfigApplyRequestTopic — MP requested config apply // bus.ConfigUploadRequestTopic — MP requested config upload // bus.NginxConfigUpdateTopic — NGINX config file changed on disk // bus.AgentConfigUpdateTopic — agent config update from MP // bus.ConnectionCreatedTopic — new gRPC connection established // bus.ConnectionAgentConfigUpdateTopic — config update from CreateConnection response // bus.EnableWatchersTopic — re-enable file/instance watchers after config apply // bus.APIActionRequestTopic — MP requested NGINX Plus API action // bus.DataPlaneHealthRequestTopic — health poll from MP // Dynamically remove a plugin at runtime _ = pipe.DeRegister(ctx, []string{"collector"}) // Check if a plugin is active if pipe.IsPluginRegistered("command") { // command plugin is running } // Live reconfigure all plugins from a new AgentConfig proto pipe.Reconfigure(ctx, newAgentConfigProto, bus.AgentConfigUpdateTopic, correlationID) ``` -------------------------------- ### Load and Register Agent Plugins Source: https://context7.com/nginx/agent/llms.txt Instantiates agent plugins based on configuration and registers them with the message pipe. Ensure `ctx` is a valid context and `agentConfig` is loaded. ```go import ( "github.com/nginx/agent/v3/internal/bus" "github.com/nginx/agent/v3/internal/plugin" "github.com/nginx/agent/v3/internal/config" ) agentConfig := config.LoadConfig() // loads from file + env + CLI // Build plugin list based on config plugins := plugin.LoadPlugins(ctx, agentConfig) // Plugins created (if configured): // - CommandPlugin (primary management plane connection) // - NginxPlugin (NGINX config apply, upload, API actions) // - CommandPlugin (auxiliary read-only management plane, if configured) // - NginxPlugin (auxiliary read-only nginx plugin, if configured) // - Collector (OTel metrics/logs, if FeatureMetrics + exporter configured) // - Watcher (always added: instance, health, file, credential watchers) // Wire plugins into the message pipe pipe := bus.NewMessagePipe(100, agentConfig) err := pipe.Register(100, plugins) if err != nil { log.Fatal(err) } // Start the event loop (blocks until ctx is cancelled) pipe.Run(ctx) ``` -------------------------------- ### File Metadata and Hash Utilities in Go Source: https://context7.com/nginx/agent/llms.txt Utilize functions for generating file metadata, SHA-256 hashes, and configuration version tokens. Also includes utilities for chunked gRPC file streaming. ```go import ( "github.com/nginx/agent/v3/pkg/files" mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1" ) // FileMeta: builds a proto FileMeta from a filesystem path meta, err := files.FileMeta("/etc/nginx/nginx.conf") // meta.Name → "/etc/nginx/nginx.conf" // meta.Hash → "base64(sha256(content))" // meta.Permissions → "0644" // meta.Size → 2048 // meta.ModifiedTime → timestamppb ``` ```go // FileMetaWithCertificate: same as FileMeta but also parses X.509 cert metadata certMeta, err := files.FileMetaWithCertificate("/etc/ssl/nginx.crt") // certMeta.FileType = *mpi.FileMeta_CertificateMeta{...} // certMeta.GetCertificateMeta().SerialNumber, Issuer, Subject, Sans, Dates, SignatureAlgorithm ``` ```go // GenerateHash: SHA-256 hash of arbitrary bytes (base64-encoded) hash := files.GenerateHash([]byte("worker_processes auto;\n")) ``` ```go // GenerateConfigVersion: stable version token for a set of files (sorted by name, hashed) configVersion := files.GenerateConfigVersion([]*mpi.File{ {FileMeta: &mpi.FileMeta{Name: "/etc/nginx/nginx.conf", Hash: hash}}, {FileMeta: &mpi.FileMeta{Name: "/etc/nginx/conf.d/default.conf", Hash: "..."}}, }) ``` ```go // ConvertToMapOfFiles: index a []*mpi.File slice by file path fileMap := files.ConvertToMapOfFiles(myFiles) // fileMap["/etc/nginx/nginx.conf"] → *mpi.File ``` ```go // Permissions / FileMode: convert between os.FileMode and octal string permStr := files.Permissions(os.FileMode(0o644)) // → "0644" mode := files.FileMode("0644") // → os.FileMode(0644) ``` ```go // SendChunkedFile / RecvChunkedFile: chunked gRPC streaming (for FileService.GetFileStream) // On the server side (sending): f, _ := os.Open("/etc/nginx/large.conf") info, _ := f.Stat() header := v1.FileDataChunk_Header{Header: &v1.FileDataChunkHeader{ FileMeta: &v1.FileMeta{Name: "/etc/nginx/large.conf", Size: info.Size()}, Chunks: uint32(math.Ceil(float64(info.Size()) / float64(chunkSize))), ChunkSize: uint32(chunkSize), }} err = files.SendChunkedFile(msgMeta, header, f, grpcServerStream) ``` ```go // On the client side (receiving): var buf bytes.Buffer receivedMeta, err := files.RecvChunkedFile(grpcClientStream, &buf) // buf.Bytes() = full file content; receivedMeta = *mpi.FileMeta ``` -------------------------------- ### Mock Server Implementation for NGINX Agent Source: https://context7.com/nginx/agent/llms.txt This Go code comment describes the purpose and suitability of the mock server. It implements the mpi.CommandServiceServer and mpi.FileServiceServer interfaces, useful for integration tests and simulating various NGINX Agent functionalities. ```go // The mock server implements the same mpi.CommandServiceServer and mpi.FileServiceServer // interfaces from api/grpc/mpi/v1, making it suitable for: // - Integration tests of config apply / config upload workflows // - Testing DataPlaneResponse handling // - Verifying NGINX Plus API action flows // - Simulating connection resets and reconnect logic ``` -------------------------------- ### NGINX Agent Update Log Level Request Example Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Example request body to update the NGINX Agent's log level to debug. ```json { "message_meta": { "message_id": "6c0fa83e-351c-4009-90cd-1f2acce2d184", "correlation_id": "11114c1c-8e91-47c1-a92c-b9a0c3f1a263", "timestamp": "2025-01-15T01:30:15.01Z" }, "update_agent_config_request": { "agent_config": { "log": { "log_level": 3 } } } } ``` -------------------------------- ### Build NGINX Agent Policy PP File Source: https://github.com/nginx/agent/blob/main/scripts/selinux/README.md Builds the nginx_agent.pp SELinux policy file using the development Makefile. This must be done on a RHEL 8 machine. ```bash make -f /usr/share/selinux/devel/Makefile nginx_agent.pp ``` -------------------------------- ### Apply Configuration to Instance Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Applies a configuration to a specific instance. ```APIDOC ## POST /api/v1/instance//config/apply ### Description Applies a configuration to a specific instance. ### Method POST ### Endpoint /api/v1/instance//config/apply ### Parameters #### Path Parameters - **instance id** (string) - Required - The ID of the instance to apply the configuration to. ### Request Body - **config_data** (object) - The configuration data to apply. ### Response #### Success Response (200) - **message** (string) - Confirmation message. ``` -------------------------------- ### NGINX Agent Update HTTP Upstream Servers Request Example Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Example request body to update HTTP upstream server configuration on the NGINX Agent. ```json { "message_meta": { "message_id": "5d0fa83e-351c-4009-90cd-1f2acce2d184", "correlation_id": "79794c1c-8e91-47c1-a92c-b9a0c3f1a263", "timestamp": "2023-01-15T01:30:15.01Z" }, "action_request": { "instance_id": "e8d1bda6-397e-3b98-a179-e500ff99fbc7", "nginx_plus_action": { "update_http_upstream_servers": { "http_upstream_name": "nginx1", "servers": [ { "max_conns": 0, "max_fails": 3, "backup": false, "down": false, "weight": 1, "server": "127.0.0.1:9081", "fail_timeout": "10s", "slow_start": "0s" } ] } } } } ``` -------------------------------- ### Enable NGINX Agent Features via CLI Source: https://context7.com/nginx/agent/llms.txt Demonstrates how to enable specific NGINX Agent features when launching the agent from the command line using the `--features` flag. Features are specified as a comma-separated list. ```bash # CLI: enable specific features at launch ./nginx-agent --features=configuration,metrics,file-watcher,certificates ``` -------------------------------- ### GetUpstreams Source: https://github.com/nginx/agent/blob/main/docs/proto/protos.md Get Upstreams for an instance. ```APIDOC ## GetUpstreams ### Description Get Upstreams for an instance. ``` -------------------------------- ### GetStreamUpstreams Source: https://github.com/nginx/agent/blob/main/docs/proto/protos.md Get Stream Upstream Servers for an instance. ```APIDOC ## GetStreamUpstreams ### Description Get Stream Upstream Servers for an instance. ``` -------------------------------- ### GetHTTPUpstreamServers Source: https://github.com/nginx/agent/blob/main/docs/proto/protos.md Get HTTP Upstream Servers for an instance. ```APIDOC ## GetHTTPUpstreamServers ### Description Get HTTP Upstream Servers for an instance. ### Fields - **http_upstream_name** ([string](#string)) - The name of the upstream. ``` -------------------------------- ### Get External File Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Retrieves a specific external file. ```APIDOC ## GET /api/v1/externalfile/ ### Description Retrieves a specific external file. ### Method GET ### Endpoint /api/v1/externalfile/ ### Parameters #### Path Parameters - **filename** (string) - Required - The name of the file to retrieve. ### Response #### Success Response (200) - **file_content** (string) - The content of the requested file. ``` -------------------------------- ### Build New Policy Script Source: https://github.com/nginx/agent/blob/main/scripts/selinux/README.md Executes a local script to build the new SELinux policy on a RHEL 8 machine. ```bash sudo ./nginx_agent.sh ``` -------------------------------- ### Get Mock Responses Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Retrieves a list of predefined mock responses. ```APIDOC ## GET /api/v1/responses ### Description Retrieves a list of predefined mock responses. ### Method GET ### Endpoint /api/v1/responses ### Response #### Success Response (200) - **responses** (array) - A list of mock response objects. ``` -------------------------------- ### Get Connection Information Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Retrieves information about the current connection status. ```APIDOC ## GET /api/v1/connection ### Description Retrieves information about the current connection status. ### Method GET ### Endpoint /api/v1/connection ### Response #### Success Response (200) - **connection_info** (object) - Details about the connection. ``` -------------------------------- ### Build All NGINX Agent Images Source: https://github.com/nginx/agent/blob/main/test/mock/collector/README.md Builds all NGINX agent images including NGINX Plus, NGINX App Protect, and the custom OTel collector. Ensure OSARCH is set to amd64 for NGINX App Protect compatibility. ```bash OSARCH=amd64 make local-deb-package build-test-nginx-plus-and-nap-image make local-deb-package build-test-oss-image build-test-plus-image build-mock-management-otel-collector-image ``` -------------------------------- ### Get Health Check Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Performs a health check on the mock management server. ```APIDOC ## GET /api/v1/health ### Description Performs a health check on the mock management server. ### Method GET ### Endpoint /api/v1/health ### Response #### Success Response (200) - **health** (string) - Indicates the health status (e.g., 'ok'). ``` -------------------------------- ### Custom Plugin Development with bus.Plugin Interface in Go Source: https://context7.com/nginx/agent/llms.txt Implement the `bus.Plugin` interface to create custom extensions for the agent's message bus. This involves defining Init, Close, Info, Process, Subscriptions, and Reconfigure methods. ```go import ( "context" "github.com/nginx/agent/v3/internal/bus" "github.com/nginx/agent/v3/internal/config" ) type MyPlugin struct { pipe bus.MessagePipeInterface cfg *config.Config } func (p *MyPlugin) Init(ctx context.Context, pipe bus.MessagePipeInterface) error { p.pipe = pipe // start background goroutines here return nil } func (p *MyPlugin) Close(ctx context.Context) error { // cancel goroutines, close connections return nil } func (p *MyPlugin) Info() *bus.Info { return &bus.Info{Name: "my-plugin"} } func (p *MyPlugin) Process(ctx context.Context, msg *bus.Message) { switch msg.Topic { case bus.NginxConfigUpdateTopic: // react to NGINX config changes nginxCtx := msg.Data.(*model.NginxConfigContext) // ... do work ... // publish a response p.pipe.Process(ctx, &bus.Message{ Topic: bus.DataPlaneResponseTopic, Data: buildDataPlaneResponse(nginxCtx), }) } } func (p *MyPlugin) Subscriptions() []string { return []string{bus.NginxConfigUpdateTopic} } func (p *MyPlugin) Reconfigure(ctx context.Context, cfg *config.Config) error { p.cfg = cfg return nil } // Register with the agent plugins := plugin.LoadPlugins(ctx, agentConfig) plugins = append(plugins, &MyPlugin{cfg: agentConfig}) pipe := bus.NewMessagePipe(256, agentConfig) _ = pipe.Register(256, plugins) pipe.Run(ctx) ``` -------------------------------- ### Get Server Status Source: https://github.com/nginx/agent/blob/main/test/mock/grpc/README.md Retrieves the current status of the mock management server. ```APIDOC ## GET /api/v1/status ### Description Retrieves the current status of the mock management server. ### Method GET ### Endpoint /api/v1/status ### Response #### Success Response (200) - **status** (string) - The current status of the server. ``` -------------------------------- ### Initialize Watcher Plugin Source: https://context7.com/nginx/agent/llms.txt Initializes the Watcher Plugin for monitoring NGINX processes, files, and health. This plugin launches several background goroutines. ```go import "github.com/nginx/agent/v3/internal/watcher" watcherPlugin := watcher.NewWatcher(agentConfig) // Launches goroutines for: // instance.InstanceWatcherService – polls for NGINX process/config changes (every 5s default) // health.HealthWatcherService – polls NGINX health (every 5s default) // file.FileWatcherService – watches allowed_directories for file changes (every 5s) // credentials.CredentialWatcherService – watches TLS credential files for rotation // watcherPlugin.Subscriptions(): // [ConfigApplyRequestTopic, DataPlaneHealthRequestTopic, // EnableWatchersTopic, AgentConfigUpdateTopic] // When NGINX config changes on disk → publishes bus.NginxConfigUpdateTopic (*model.NginxConfigContext) // When instance health changes → publishes bus.InstanceHealthTopic ([]*mpi.InstanceHealth) // When resource (process) changes → publishes bus.ResourceUpdateTopic (*mpi.Resource) // When credentials rotate → publishes bus.ConnectionResetTopic (GrpcConnectionInterface) // During config apply: watchers are disabled to avoid false-positive change events // After config apply completes: re-enabled via bus.EnableWatchersTopic ```