Skip to main content
Version: v25.5 (latest)

Anonymous Access

The anonymous option of the --security superflag sets what a caller with no verified credential can do. You choose one of three postures: full, data, or none. The default is full, which keeps the behavior of every earlier release.

# Anonymous callers can query and mutate, but cannot administer the cluster
dgraph alpha --security "token=<authtokenstring>; anonymous=data"

This page is a reference and an explanation. It covers why the option exists, exactly what each posture allows, how a caller becomes identified, and how to move a running cluster to a closed posture.

Why this option exists​

Three settings protect the privileged operations on Dgraph Alpha:

SettingQuestion it answersBehavior when you leave it unset
--security "whitelist=..."Where did the request come from?Only loopback callers pass. Every other address is rejected.
--security "token=..."Does the caller know the shared secret?No token is required from anyone.
--acl "secret-file=..."Which user is this, and what may they do?Guardian checks succeed for everyone.

Each setting passes when its own feature is unconfigured. The protection you get is whatever you configured, rather than the combination of all three.

The default is safe because the empty whitelist admits loopback only. The risk appears when you widen the whitelist. The whitelist checks the network location of a request and carries no credential. If you set whitelist=0.0.0.0/0 and configure neither a token nor ACL, then any caller that can reach the port can back up, restore, export, or shut down your cluster without presenting any credential at all.

The anonymous option makes that decision explicit. It answers a fourth question: what may a caller do when nothing has identified them?

tip

whitelist=0.0.0.0/0 is common in containers and quickstart setups, because the Docker host reaches a published port from a non-loopback address. If you run Dgraph that way, read Choose a posture.

Postures​

PostureAnonymous callers canAnonymous callers cannotWhen to use it
full (default)Do whatever the whitelist, token, and ACL settings allow.Nothing changes from earlier releases.Existing clusters, and clusters that rely on network isolation alone.
dataRun queries, mutations, and commits. Log in. Read /health.Perform any administrative operation, including schema changes and drops, no matter what the whitelist allows.Clusters that serve application traffic without credentials but must protect the control plane.
noneLog in, call CheckVersion, and read the health and readiness endpoints.Run queries, mutations, or commits, or perform any administrative operation.Clusters where every client authenticates.

The value is not case-sensitive. Alpha and Zero refuse to start on any other value:

--security "anonymous=closed" is not a valid value; it must be one of full, data, or none

What counts as an identified caller​

A request is identified when it presents a credential that Dgraph verifies. A request that presents no credential, or one that fails verification, is anonymous.

CredentialHow to send it over HTTPHow to send it over gRPCIdentifies the caller when
ACL access JWTX-Dgraph-AccessToken headeraccessJwt metadata keyACL is enabled and the JWT is valid and unexpired
--security auth tokenX-Dgraph-AuthToken headerauth-token metadata keyA token is configured and the value matches it

A few rules follow from this table:

  • A token identifies a caller only when you configure one. If you set anonymous=data without a token or ACL, no request can ever be identified, so no one can administer the cluster. Dgraph logs a warning at startup when it detects this. See Startup warnings.
  • The source IP never identifies a caller. Loopback and whitelisted addresses count as anonymous under data and none.
  • When a request carries both credentials, the ACL user wins. The ACL JWT identifies a person, while the token identifies a client service.
  • An identity does not bypass the other settings. The posture decides whether an anonymous caller is turned away. It does not grant anything. An identified caller still has to pass the whitelist, token, and ACL checks that applied before.
note

With ACL enabled, a caller who presents only the --security token is identified, but ACL rules still decide what they may do. The token does not grant administrative authority on an ACL cluster. Use the credentials of a Guardian user for administration.

What each posture allows​

This table lists the operations the posture affects. "Unchanged" means the operation follows the whitelist, token, and ACL rules exactly as it did before the anonymous option existed.

Data operations​

OperationHTTPgRPCfulldatanone
Query/queryQuery, RunDQLUnchangedUnchangedRequires identity
Mutation/mutateQuery with mutations, RunDQLUnchangedUnchangedRequires identity
Commit or abort/commitCommitOrAbortUnchangedUnchangedRequires identity
GraphQL queries and mutations/graphqlUnchangedUnchangedRequires identity

Administrative operations​

Every operation in this table requires an identified caller under data and none.

Every request to /alter counts as administrative, schema changes included. Dgraph has always treated /alter as an admin operation: it requires a whitelisted address and, when one is configured, the token. Under data, it additionally requires a credential, so an application that changes its own schema at startup needs to send the token.

caution

Dropping is not limited to drop_all. drop_op: DATA removes every node in a namespace in one request. Under data and none, all of these require an identified caller.

OperationWherefull
Schema change/alter, gRPC AlterUnchanged
Drop a predicate, a type, or all data in a namespace/alter with drop_attr or drop_op, gRPC AlterUnchanged
Drop all data/alter with drop_all, gRPC AlterUnchanged
Create, drop, or list namespacesgRPC CreateNamespace, DropNamespace, ListNamespaces; /admin addNamespace, deleteNamespaceUnchanged
Lease UIDsgRPC AllocateIDsUnchanged
Act in another namespaceGalaxy-wide loads, such as dgraph live --force-namespaceUnchanged
Read cluster state/state, /health?all, /admin stateUnchanged
Backups/admin backup, restore, restoreTenant, listBackupsUnchanged
Exports/admin exportUnchanged
Cluster control/admin shutdown, draining, removeNode, moveTablet, assign, config; /admin/shutdown, /admin/draining, /admin/config/cache_mbUnchanged
GraphQL schema/admin/schema, /admin updateGQLSchema, getGQLSchemaUnchanged
Password reset/admin resetPasswordUnchanged
External snapshot importgRPC UpdateExtSnapshotStreamingState, StreamExtSnapshotUnchanged

Operations that stay open​

The posture never blocks these operations. They are how a client obtains a credential, or how infrastructure checks that a node is alive.

They keep the rules that applied before. In particular, /login still requires a whitelisted address and, when you configure one, the token. On a cluster with a token, send X-Dgraph-AuthToken along with the login request.

OperationWhere
Log in/login, gRPC Login, /admin login
Version checkgRPC CheckVersion
Health/health (without ?all), gRPC grpc.health.v1.Health
GraphQL readiness/probe/graphql
caution

/state and /health?all are administrative under data and none. If your monitoring, readiness probes, or test tooling read /state without a credential, they start receiving Unauthenticated errors. Point them at /health, or send the token.

Choose a posture​

Use the scenario that matches your deployment.

You run Dgraph on a single host and only administer it from that host. Keep full. The empty whitelist already limits administrative operations to loopback.

You widened the whitelist so other hosts or containers can reach Alpha, and you have no ACL. Set a token and move to data. Queries and mutations keep working without credentials. Administration, including schema changes, requires the token.

dgraph alpha --security "whitelist=0.0.0.0/0; token=<authtokenstring>; anonymous=data"

You run ACL and every application already logs in. Move to none. Anonymous requests can no longer read or write data, even predicates that no ACL rule covers.

dgraph alpha --acl "secret-file=/dgraph/acl/hmac_secret" --security "anonymous=none"

You run a multi-tenant cluster. Use data or none together with ACL. The posture stops an anonymous caller from reaching namespace lifecycle operations, while ACL continues to decide what each tenant's users may do.

Examples​

The examples use a token named s3cr3t. Use a long random value in production, for example the output of openssl rand -hex 32.

Protect the control plane with a token​

Start Alpha with an open whitelist, a token, and the data posture:

dgraph alpha --security "whitelist=0.0.0.0/0; token=s3cr3t; anonymous=data"

Queries and mutations work without a credential:

curl -s -H 'Content-Type: application/dql' localhost:8080/query \
-d '{ q(func: has(name)) { name } }'
{"data":{"q":[]},"extensions":{...}}

Reading cluster state without the token is refused:

curl -s localhost:8080/state
{"errors":[{"message":"rpc error: code = Unauthenticated desc = the tenant-admin capability requires an identified caller, and this request presented no credential that verified. This cluster runs with --security \"anonymous=data\". Present the --security auth token, or log in with ACL."}]}

The same request with the token succeeds:

curl -s -H 'X-Dgraph-AuthToken: s3cr3t' localhost:8080/state

Administer through the GraphQL admin endpoint​

Send the token in the X-Dgraph-AuthToken header on /admin requests:

curl -s localhost:8080/admin \
-H 'Content-Type: application/json' \
-H 'X-Dgraph-AuthToken: s3cr3t' \
-d '{"query":"mutation { export(input: {format: \"rdf\"}) { response { code message } } }"}'

Without the header, the mutation fails before it runs:

{"errors":[{"message":"Invalid X-Dgraph-AuthToken","extensions":{"code":"ErrorUnauthorized"}}]}

Require a credential for everything​

Under none, an anonymous query is refused:

dgraph alpha --security "token=s3cr3t; anonymous=none"

curl -s -H 'Content-Type: application/dql' localhost:8080/query \
-d '{ q(func: has(name)) { name } }'
{"errors":[{"message":"rpc error: code = Unauthenticated desc = query requires an identified caller, and this request presented no credential that verified. This cluster runs with --security \"anonymous=none\". Present the --security auth token, or log in with ACL."}]}

Health checks keep working, so readiness probes are unaffected:

curl -s localhost:8080/health

Send the token from a gRPC client​

Over gRPC, put the token in the auth-token metadata key. In Go:

import "google.golang.org/grpc/metadata"

ctx = metadata.AppendToOutgoingContext(ctx, "auth-token", "s3cr3t")
resp, err := client.Alter(ctx, op)

Configure the option in a config file​

The option is part of the security superflag in a YAML config file:

security:
token: s3cr3t
whitelist: 10.0.0.0/8
anonymous: data

Or as an environment variable:

export DGRAPH_ALPHA_SECURITY="whitelist=10.0.0.0/8; token=s3cr3t; anonymous=data"
dgraph alpha

Dgraph Zero​

Zero reads the same --security superflag. On Zero, anonymous controls its administrative HTTP endpoints on port 6080.

Endpointfulldata or none
/removeNode, /moveTabletToken, or a whitelisted address. Loopback only by default.Token required. A whitelisted address is not enough.
/state, /assignOpen until you configure a token or whitelist.Token required.
/healthOpenOpen

Zero has no ACL, so under data or none the token is the only credential it accepts. Configure one, or no caller can reach Zero's administrative endpoints, including from loopback.

dgraph zero --security "token=s3cr3t; anonymous=data"

# Refused, even from the Zero host itself
curl -s localhost:6080/state

# Allowed
curl -s -H 'X-Dgraph-AuthToken: s3cr3t' localhost:6080/state
tip

Set the same posture on Alpha and Zero. A cluster where only Alpha is closed still exposes Zero's control plane to anything inside Zero's whitelist.

Startup warnings​

Alpha checks your --security settings at startup and logs a warning that begins with SECURITY: when they combine badly.

ConfigurationWarningWhat to do
full, a widened whitelist, and neither a token nor ACLPrivileged operations are reachable from the whitelist range without any credential.Set a token or enable ACL, and narrow the whitelist. Consider anonymous=data.
data or none, and neither a token nor ACLNo request can be identified, so the cluster cannot be administered, including from loopback.Set a token or enable ACL.

Zero logs the second warning when you set data or none without a token.

Move a cluster to a closed posture​

Follow these steps to move an existing cluster from full to data without an interruption.

  1. Upgrade every Alpha and Zero to a release that supports the anonymous option. A node on an older release refuses to start with it.
  2. Choose a credential. Set a token on every Alpha and Zero with --security "token=...", or enable ACL. Restart the nodes.
  3. Update your tooling. Send the token from every script, dashboard, and probe that performs administrative operations, changes the schema, or reads /state. Leave the posture at full while you do this, so nothing breaks yet.
  4. Check the tools that load data. dgraph live leases UIDs through an administrative operation. See Known limitations before you continue.
  5. Set anonymous=data on every Zero, then every Alpha, and restart them one at a time.
  6. Confirm the result. An anonymous request to /state returns Unauthenticated, a request with the token succeeds, and the startup log has no SECURITY: warnings.

To return to the previous behavior, set anonymous=full and restart.

Known limitations​

  • dgraph live with only --auth_token cannot load data under data or none. The loader leases UIDs through the AllocateIDs operation, and it does not send the token on that request. The request is refused and the loader retries without making progress. Use ACL credentials instead, which the loader does send:

    dgraph live -f data.rdf -s data.schema -a localhost:9080 -z localhost:5080 \
    --creds "user=groot;password=password;namespace=0"

    On a cluster without ACL, keep anonymous=full while you run the live loader.

  • dgraph increment and dgraph import have no --auth_token option. Use ACL credentials with them on a closed cluster.

  • dgraph bulk is not affected. It talks only to Zero's gRPC port, which the posture does not govern.

Upgrades and mixed versions​

Dgraph rejects any superflag option it does not recognize, so that a typo fails at startup instead of being silently ignored. An Alpha or Zero from a release that predates the anonymous option exits when it sees the option:

superflag: found invalid options: anonymous=data.
valid options: token=; whitelist=;

Upgrade every node before you set the option. This applies to config files and environment variables too, because they feed the same superflag.

Default value and future releases​

The default is full so that upgrading changes nothing for an existing cluster. A future major release is planned to change the default to data. To prepare, set a token or enable ACL now, and set anonymous=data explicitly to confirm your tooling works with it.

See also​