syntax = "proto3"; package containarr.agent.v1; option go_package = "github.com/containarr/server/internal/proto/agentv1"; // ── Shared types ───────────────────────────────────────────────────────────── message ContainerPort { uint32 host_port = 1; uint32 container_port = 2; string protocol = 3; string host_ip = 4; } message ContainerInfo { string id = 1; string name = 2; string image = 3; string status = 4; string state = 5; repeated ContainerPort ports = 6; int64 created_at = 7; map labels = 8; string compose_project = 9; } // ── Agent → Server ──────────────────────────────────────────────────────────── message AgentHandshake { string token = 1; string hostname = 2; string arch = 3; string os = 4; string ip_address = 5; } message ImageInfo { string id = 1; repeated string tags = 2; int64 size = 3; int64 created_at = 4; bool is_orphan = 5; } message VolumeInfo { string name = 1; string driver = 2; string mountpoint = 3; bool is_orphan = 4; } message NetworkInfo { string id = 1; string name = 2; string driver = 3; string scope = 4; bool is_orphan = 5; } message ContainerSnapshot { repeated ContainerInfo containers = 1; int64 timestamp = 2; repeated ImageInfo images = 3; repeated VolumeInfo volumes = 4; repeated NetworkInfo networks = 5; } message CommandResult { string command_id = 1; bool success = 2; string error = 3; } message LogChunk { string container_id = 1; string stream = 2; // "stdout" | "stderr" bytes data = 3; int64 timestamp = 4; } message FileResult { string command_id = 1; bool success = 2; string error = 3; bytes content = 4; // for ReadFile: file content; for ListDir: JSON-encoded entries } message UpdateCheckResult { string command_id = 1; string container_id = 2; bool update_available = 3; string current_digest = 4; string remote_digest = 5; string error = 6; } message ProcessInfo { uint32 pid = 1; string name = 2; string cmd = 3; double cpu_pct = 4; uint64 mem_rss = 5; } message NetworkInterfaceStats { string name = 1; uint64 bytes_recv = 2; uint64 bytes_sent = 3; uint64 bytes_recv_rate = 4; // bytes/s since last snapshot uint64 bytes_sent_rate = 5; } message DiskStats { string path = 1; uint64 total = 2; uint64 used = 3; uint64 free = 4; } message StatsSnapshot { double cpu_pct = 1; repeated double cpu_per_core = 2; uint64 mem_total = 3; uint64 mem_used = 4; uint64 mem_available = 5; repeated NetworkInterfaceStats net_interfaces = 6; repeated ProcessInfo processes = 7; repeated DiskStats disks = 8; int64 timestamp = 9; } message AgentMessage { oneof payload { AgentHandshake handshake = 1; ContainerSnapshot snapshot = 2; CommandResult result = 3; LogChunk log_chunk = 4; FileResult file_result = 5; UpdateCheckResult update_check_result = 6; StatsSnapshot stats_snapshot = 7; } } // ── Server → Agent ──────────────────────────────────────────────────────────── enum ContainerAction { CONTAINER_ACTION_UNSPECIFIED = 0; CONTAINER_ACTION_START = 1; CONTAINER_ACTION_STOP = 2; CONTAINER_ACTION_RESTART = 3; CONTAINER_ACTION_REMOVE = 4; } message ContainerCommand { string command_id = 1; string container_id = 2; ContainerAction action = 3; } message StreamLogsCommand { string command_id = 1; string container_id = 2; bool follow = 3; int32 tail = 4; } message ListDirCommand { string command_id = 1; string path = 2; } message ReadFileCommand { string command_id = 1; string path = 2; } message WriteFileCommand { string command_id = 1; string path = 2; bytes content = 3; } message ExecComposeCommand { string command_id = 1; string path = 2; // directory containing docker-compose.yaml string action = 3; // "up", "down", "pull" } message CreateDirCommand { string command_id = 1; string path = 2; } message CheckUpdateCommand { string command_id = 1; string container_id = 2; } message UpdateContainerCommand { string command_id = 1; string container_id = 2; } message DeleteImageCommand { string command_id = 1; string image_id = 2; bool force = 3; } message DeleteVolumeCommand { string command_id = 1; string volume_name = 2; bool force = 3; } message DeleteNetworkCommand { string command_id = 1; string network_id = 2; } message ServerMessage { oneof payload { ContainerCommand container_cmd = 1; StreamLogsCommand stream_logs = 2; ListDirCommand list_dir = 3; ReadFileCommand read_file = 4; WriteFileCommand write_file = 5; ExecComposeCommand exec_compose = 6; CreateDirCommand create_dir = 7; CheckUpdateCommand check_update = 8; UpdateContainerCommand update_container = 9; DeleteImageCommand delete_image = 10; DeleteVolumeCommand delete_volume = 11; DeleteNetworkCommand delete_network = 12; } } // ── Service ─────────────────────────────────────────────────────────────────── service AgentGateway { // Bidirectional stream: agent connects once and maintains the tunnel. // First AgentMessage must be AgentHandshake. rpc Tunnel(stream AgentMessage) returns (stream ServerMessage); }