# How to Configure gRPC Transport in Xray-core with Custom Service Names

> Learn to configure gRPC transport in Xray-core with custom service names. Set serviceName in grpcSettings for plain strings or hierarchical paths. Optimize your Xray-core setup.

- Repository: [Project X Community, Not Porn-jet X Hub/Xray-core](https://github.com/XTLS/Xray-core)
- Tags: how-to-guide
- Published: 2026-04-21

---

**To configure gRPC transport in Xray-core with custom service names, set the `serviceName` field in `grpcSettings`—use a plain string for classic mode or a slash-prefixed path with pipe-separated stream names for hierarchical services.**

Xray-core implements gRPC as a native Internet transport, with configuration parsing in [`transport/internet/grpc/config.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/config.go) and listener implementation in [`transport/internet/grpc/hub.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/hub.go). The `serviceName` field supports two distinct modes: simple strings for standard deployments and custom hierarchical paths for advanced multi-service configurations.

## Understanding gRPC Service Name Parsing in Xray-core

The `Config` struct in [`transport/internet/grpc/config.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/config.go) provides three key methods that determine how your `serviceName` value is interpreted:

| Method | Purpose | Source Location |
|--------|---------|-----------------|
| `getServiceName()` | Returns the registered gRPC service name, with URL-escaping for simple names or path-component extraction for slash-prefixed values | [`config.go`](https://github.com/XTLS/Xray-core/blob/main/config.go) lines 17-34 |
| `getTunStreamName()` | Determines the Tun stream name—defaults to `"Tun"` for classic configs, or extracts the segment after the last `/` (respecting `\|` separators) | [`config.go`](https://github.com/XTLS/Xray-core/blob/main/config.go) lines 36-44 |
| `getTunMultiStreamName()` | Determines the TunMulti stream name—uses the second component after `\|` splitting on the server side | [`config.go`](https://github.com/XTLS/Xray-core/blob/main/config.go) lines 46-58 |

### Slash-prefixed vs. plain service names

When `serviceName` **does not** start with `/`, Xray-core treats it as a simple identifier. The value is URL-escaped and used directly as the service name, with `"Tun"` as the default stream name.

When `serviceName` **starts with `/`**, Xray-core interprets it as a hierarchical path. The path components (everything between the first and last `/`) become the service name, while segments after the final `/`—split by `|`—determine custom stream names for Tun and TunMulti RPCs.

## Classic gRPC Configuration (Simple Service Name)

For most deployments, use a plain string without leading slashes. This creates a standard gRPC service with default stream naming.

### Client configuration

```yaml
inbounds:
  - port: 1080
    protocol: socks
    settings:
      auth: noauth
    streamSettings:
      network: grpc
      grpcSettings:
        serviceName: myservice
        multiMode: false

```

### Server configuration

```yaml
inbounds:
  - port: 2080
    protocol: vmess
    settings:
      clients:
        - id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    streamSettings:
      network: grpc
      grpcSettings:
        serviceName: myservice
        multiMode: false

```

**Internal behavior:** The `getServiceName()` method returns `"myservice"` (URL-escaped). `getTunStreamName()` returns `"Tun"`. No TunMulti stream is registered when `multiMode: false`.

## Custom Hierarchical Service Names with Multiple Streams

Advanced deployments can use slash-prefixed paths to specify custom service hierarchies and distinct stream names for Tun and TunMulti RPCs.

### Configuration with custom stream names

```yaml

# Client configuration

inbounds:
  - port: 1080
    protocol: socks
    streamSettings:
      network: grpc
      grpcSettings:
        serviceName: "/myapp/api/v1|tunnel|multistream"
        multiMode: true

```

```yaml

# Server configuration

inbounds:
  - port: 2080
    protocol: vmess
    settings:
      clients:
        - id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    streamSettings:
      network: grpc
      grpcSettings:
        serviceName: "/myapp/api/v1|tunnel|multistream"
        multiMode: true

```

### How Xray-core parses this value

| Component | Resolved Value | Source Method |
|-----------|--------------|---------------|
| Service name | `myapp/api/v1` | `getServiceName()` |
| Tun stream name | `tunnel` | `getTunStreamName()` |
| TunMulti stream name | `multistream` | `getTunMultiStreamName()` |

The listener in [`transport/internet/grpc/hub.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/hub.go) logs these resolved names at line 27-29 and registers two RPC methods:

- `/myapp/api/v1/tunnel` — handles single-stream connections
- `/myapp/api/v1/multistream` — handles multiplexed connections when `multiMode: true`

## Enabling TLS with Custom gRPC Service Names

Production deployments should wrap gRPC in TLS. The TLS configuration is processed in `transport/internet/tls/` and passed to the gRPC server via `grpc.Creds()`.

### TLS-enabled server configuration

```yaml
inbounds:
  - port: 443
    protocol: vmess
    settings:
      clients:
        - id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    streamSettings:
      network: grpc
      security: tls
      tlsSettings:
        alpn: ["h2"]
        certificates:
          - certificateFile: /path/to/cert.pem
            keyFile: /path/to/key.pem
      grpcSettings:
        serviceName: "/secure/service|secureTun|secureMulti"
        multiMode: true

```

Internally, `tls.ConfigFromStreamSettings()` in the TLS package constructs a `tls.Config`, which the hub passes to `credentials.NewTLS()` at [`hub.go`](https://github.com/XTLS/Xray-core/blob/main/hub.go) lines 80-85.

## Key Source Files for gRPC Transport

| File | Purpose | Direct Link |
|------|---------|-------------|
| [`transport/internet/grpc/config.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/config.go) | `Config` struct with `getServiceName()`, `getTunStreamName()`, `getTunMultiStreamName()` | [config.go](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/config.go) |
| [`transport/internet/grpc/hub.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/hub.go) | gRPC listener, server creation, service registration, TLS integration | [hub.go](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/hub.go) |
| [`transport/internet/grpc/config.pb.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/config.pb.go) | Protobuf-generated configuration types | [config.pb.go](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/config.pb.go) |
| `transport/internet/tls/*.go` | TLS configuration utilities | [tls package](https://github.com/XTLS/Xray-core/tree/main/transport/internet/tls) |
| `transport/internet/grpc/encoding/*.go` | Generated gRPC service stubs | [encoding package](https://github.com/XTLS/Xray-core/tree/main/transport/internet/grpc/encoding) |

## Summary

- **Plain service names** (no leading `/`) create standard gRPC services with default `"Tun"` stream naming—use for simple deployments.
- **Slash-prefixed paths** enable hierarchical service names and custom Tun/TunMulti stream names, split by `|` delimiters.
- The `getServiceName()`, `getTunStreamName()`, and `getTunMultiStreamName()` methods in [`transport/internet/grpc/config.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/config.go) control all name resolution.
- The listener in [`transport/internet/grpc/hub.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/hub.go) logs resolved names and registers RPC methods accordingly.
- Combine with TLS via `security: tls` and `tlsSettings` for production use.

## Frequently Asked Questions

### What happens if I omit the leading slash in serviceName?

Without a leading `/`, Xray-core treats `serviceName` as a simple identifier. The value is URL-escaped and used directly as the service name, and `getTunStreamName()` returns the default `"Tun"`. This is the classic mode suitable for most basic deployments.

### Can I use custom stream names without multiMode enabled?

Yes, but the custom TunMulti stream name will only be used when `multiMode: true`. With `multiMode: false`, Xray-core registers only the Tun stream. The pipe-separated syntax still parses correctly—the unused TunMulti name is simply ignored during service registration in [`hub.go`](https://github.com/XTLS/Xray-core/blob/main/hub.go).

### How do I verify my custom service names are registered correctly?

Check the Xray-core logs at debug level. The listener in [`transport/internet/grpc/hub.go`](https://github.com/XTLS/Xray-core/blob/main/transport/internet/grpc/hub.go) logs the resolved service name and stream names at line 27-29:

```

gRPC listen for service name `myapp/api/v1` tun `tunnel` multi tun `multistream`

```

If these values match your intended configuration, the gRPC service is registered correctly.