Skip to content

Configuration

Danny edited this page Oct 13, 2026 · 9 revisions

Configuration

LoadConfig

vngcloud.LoadConfig(ctx, opts...) resolves a Config from options, environment variables, and AWS-style profile files, the way the AWS CLI resolves its own configuration. vngcloud.NewConfig builds a Config from options only, reading no environment variables or files; LoadConfig is the default choice for a program or script that should pick up a profile:

cfg, err := vngcloud.LoadConfig(ctx, vngcloud.WithRegion("hcm-3"))
if err != nil {
	log.Fatal(err)
}

Precedence

Highest first:

  1. Options passed to LoadConfig.
  2. Environment variables.
  3. The resolved profile's section in the config and credentials files.

Nil auth/provider options and an empty static token count as unset. A non-nil auth/provider option selects the options source even when its fields are empty. Within options, WithCredentialsProvider wins over WithStaticToken, then WithServiceAccount, then WithIAMUser, regardless of option order.

Only when no option selects credentials does the first environment or file source with a non-empty credential value win. Empty environment variables and file keys count as unset. Within that source, a static token wins over service-account keys, then IAM User fields. A selected partial or malformed set fails without falling back or taking fields from another source.

WithProfile(name) selects a profile explicitly; VNGCLOUD_PROFILE never does. An explicit profile skips environment variables for credentials and the project ID, so a .env file meant for one account can never send a call made with another profile to that account. Region names no account, so it may still come from the environment even with an explicit profile. An explicit profile with no credentials, from options or its own file section, fails with vngcloud.ErrNoCredentials naming the profile.

Environment variables

Variable Meaning
VNGCLOUD_PROFILE Profile name; default default
VNGCLOUD_REGION Region
VNGCLOUD_PROJECT_ID Project ID
VNGCLOUD_ROOT_EMAIL, VNGCLOUD_USERNAME, VNGCLOUD_PASSWORD, VNGCLOUD_TOTP_SECRET IAM User credentials
VNGCLOUD_CLIENT_ID, VNGCLOUD_CLIENT_SECRET Service-account credentials
VNGCLOUD_ACCESS_TOKEN Static token; wins over service-account and IAM User values
VNGCLOUD_VCDN_API_KEY vCDN API key; see vCDN API key
VNGCLOUD_CONFIG_FILE Config file path
VNGCLOUD_SHARED_CREDENTIALS_FILE Credentials file path

Files

By default LoadConfig reads ~/.vngcloud/config and ~/.vngcloud/credentials, or the paths from WithConfigFile / WithSharedCredentialsFile or their environment variables. A missing default file is fine; a missing explicit path is an error.

# ~/.vngcloud/config
[default]
region = hcm-3

[profile dev]
region = han-1
project_id = <project-id>
# ~/.vngcloud/credentials (mode 0600)
[default]
root_email = <root-email>
username = <iam-username>
password = <password>
totp_secret = <base32-secret>

[dev]
root_email = <root-email>
username = <iam-username>
password = <password>

[service-agent]
client_id = <client-id>
client_secret = <client-secret>

Config sections other than default use the profile prefix; credentials sections use the bare profile name either way. Store client_id and client_secret only in the credentials file. Either non-empty key in the resolved config section fails with vngcloud.ErrInvalidConfig, even when another auth method wins. Other unknown keys are ignored. A named profile that appears in neither file is an error naming it. The credentials file has no access token key: a static token comes only from WithStaticToken or VNGCLOUD_ACCESS_TOKEN.

Service-account profile

Create the account with a trusted IAM-user provisioner and a new private secret-file path:

vngcloud --profile provisioner iam create-service-account \
  --name <name> --secret-file /private/new-secret

The create response supplies the ID and secret. The confirm read supplies ServiceAccount.ClientID. If confirmation fails, the CLI keeps the account and writes the returned secret; recover ClientID with iam get-service-account --service-account-id <id>. Do not create again. If no secret was returned, use the existing reset command. Secret files use exclusive mode 0600 creation and refuse existing paths and symlinks. Keep the existing command's recovery instructions if file writing fails.

Use a fresh profile to avoid leftover IAM credentials:

vngcloud --profile machine configure set region hcm-3
vngcloud --profile machine configure set project_id <project-id>
vngcloud --profile machine configure set client_id <client-id>
vngcloud --profile machine configure set client_secret - < /private/new-secret
vngcloud --profile machine configure set read_only 1

client_secret accepts piped stdin only, never argv or --cli-input-json. Stdin has a 4096-byte bound and drops one trailing LF or CRLF. A terminal on stdin is refused. configure get and configure list mask the secret; client ID may print but remains account data. Interactive configure keeps its IAM-user prompt order and does not ask for these two keys.

Set read_only last. The profile latch refuses later configure writes, including rotation. A trusted editor or provisioner must replace the protected credentials after the trusted IAM-user provisioner runs:

vngcloud --profile provisioner iam reset-service-account-secret \
  --service-account-id <id> --yes --secret-file /private/replacement-secret

Rebuild SDK configs and restart consumers after replacing credentials. Old processes can keep issued tokens and old cache entries, then fail when they need to exchange the old secret. The new secret selects a fresh cache entry. Rotation does not purge entries or promise immediate revocation of issued tokens. See Authentication and IAM commands.

vCDN API key

The cdn package's vCDN calls take an API key, not an IAM token. The key resolves on its own, highest first: WithCDNAPIKey(key), then VNGCLOUD_VCDN_API_KEY (skipped when the profile is explicit, as for every credential), then vcdn_api_key in the profile's credentials section, which keeps the mode 0600 check. No flag carries it.

The key does not select token authentication: LoadConfig still fails with vngcloud.ErrNoCredentials when no token credential set resolves. A key that holds whitespace or a control character, or is over 4 KiB, fails with vngcloud.ErrInvalidConfig naming the source and never the value. The Config has no getter for the key, and no error, log, or formatted value holds it. See CDN.

Profile settings

Config.ProfileSetting(key) returns key's value in the resolved profile's config section, or "" when there is no such key. NewConfig builds a Config with no profile, so it always returns "". The SDK does not act on any key through this method; it exists for a caller, such as the vngcloud CLI, that keeps its own settings (output, read_only) in the same config file:

cfg, err := vngcloud.LoadConfig(ctx)
if err != nil {
	log.Fatal(err)
}
output := cfg.ProfileSetting("output") // "" if the profile has no such key

File safety

LoadConfig opens the credentials file, checks the open file's mode, and refuses it when group or others can read it, naming the file and the fix (chmod 600); this check is skipped on Windows. A path that is not a regular file, such as a directory or a FIFO, is an error.

LoadConfig returns ctx.Err() directly, unwrapped, when the context passed in is already canceled or past its deadline. Every other error from LoadConfig matches vngcloud.ErrInvalidConfig via errors.Is. A missing credential set, or one source setting some IAM User credentials but not all of root_email, username, and password, also matches vngcloud.ErrNoCredentials. A selected service-account set missing client_id or client_secret matches both errors, naming the source and missing fields. Malformed service-account fields match only vngcloud.ErrInvalidConfig: each field must be at most 4096 bytes with no whitespace or control characters, and the client ID must contain no colon. Option and environment values are not trimmed. Files use the existing INI value parsing. A credentials file problem (missing at an explicit path, unreadable, refused for unsafe permissions, or malformed) also matches vngcloud.ErrCredentialsFile. No error from LoadConfig names a credential value.

A token cache directory that group or others can access is refused separately: that check runs at the first call that needs a token (Authenticate or any request), not from LoadConfig itself, and its error does not match vngcloud.ErrInvalidConfig.

Read-only agent profile

A profile for an agent that may read but never write. Pick a profile name, here agent, and pass --profile agent to every command. Set the read-only key last: once it is on, configure set refuses to run for that profile.

vngcloud --profile agent configure set region hcm-3
vngcloud --profile agent configure set root_email <root-email>
vngcloud --profile agent configure set username <iam-username>
printf '%s' "$PASSWORD" | vngcloud --profile agent configure set password -
printf '%s' "$TOTP_SECRET" | vngcloud --profile agent configure set totp_secret -
vngcloud --profile agent configure set read_only 1
  • region has no default. Use hcm-3 for HCM03. Without it, or without VNGCLOUD_REGION, commands fail with a missing-region error.
  • password and totp_secret are read from stdin only. totp_secret is optional and applies to accounts with TOTP on.
  • project_id is optional. Set it when the IAM user sees more than one project.
  • read_only 1 makes every write command exit with code 2 before any request. Only editing the config file by hand turns it off.

Check the profile with a read, which also proves the credentials work:

vngcloud --profile agent portal get-user-info
vngcloud --profile agent portal list-zones

vngcloud --profile agent configure list shows what the profile holds, with secrets masked.

Region

Config.Region selects the region, for example hcm-3 or han-1. A client serves one region.

Project

Config.ProjectID is optional. When a method needs a project and none is set, the SDK lists the projects visible to the IAM User in the region and uses the only match. If more than one project matches, set ProjectID.

List projects yourself with the project package:

projects, err := project.New(cfg).ListProjects(ctx, nil)

Or for another region:

projects, err := project.New(cfg).ListProjects(ctx, &project.ListProjectsInput{
	Region: "han-1",
})

Endpoints

The SDK targets the GreenNode domains (*.console.greennode.ai, signin.greennode.ai) by default. The old *.vngcloud.vn hosts redirect to them and drop the Authorization header on the way, so the SDK refuses cross-host redirects and returns an error instead.

Override the corresponding management endpoints with WithEndpointOverrides, passed to NewConfig alongside the region and auth options:

cfg, err := vngcloud.NewConfig(
	vngcloud.WithRegion("hcm-3"),
	vngcloud.WithIAMUser(iamUser),
	vngcloud.WithEndpointOverrides(vngcloud.EndpointOverrides{
		Dashboard: "https://custom-dashboard.example.com",
	}),
)
if err != nil {
	log.Fatal(err)
}
computeClient := compute.New(cfg)

Dashboard sets the OAuth redirect URI used during IAM login. Setting it also derives the Token endpoint, unless you set Token too.

These overrides do not change the fixed service-account token exchange or the native storage.ObjectClient regional HTTPS hosts. The object client uses its own configuration. See Storage Workload Access for the public and private connectivity boundaries.

Retries

The management retry policy uses jittered exponential backoff for eligible network errors and HTTP 429, 502, 503, and 504, and honors Retry-After. Each operation controls whether a request can retry. Change the count and base interval with WithRetry(count, interval). Cancel the context to stop retrying.

Some writes send once, including after 429 or 401. Follow the operation's recovery guidance before repeating it, such as S3 key recovery or Public NAT. The service-account exchange and native object operations also send once and do not use this retry option. vngcloud.IsRetryable(err) classifies the returned error; it does not establish that repeating an ambiguous write is safe.

Token cache

vngcloud.WithTokenCache(dir) turns on an on-disk token cache shared across processes. The CLI enables ~/.vngcloud/cache by default when a home directory exists; the SDK enables disk caching only with this option. A program run repeatedly, or several programs sharing one profile, can reuse a token instead of logging in once per process:

cfg, err := vngcloud.NewConfig(
	vngcloud.WithRegion("hcm-3"),
	vngcloud.WithIAMUser(iamUser),
	vngcloud.WithTokenCache("/home/user/.vngcloud/cache"),
)

IAM User and service-account credentials use the cache. A static token or a custom CredentialsProvider is never written to disk, and without WithTokenCache the SDK writes nothing.

WithProfile(name) adds a profile name to the cache key, so tokens for different profiles sharing one cache directory never collide. Direct NewConfig callers usually do not need it; LoadConfig sets it from the resolved profile automatically.

IAM User entries remain <dir>/<hash>.json. Their SHA-256 key includes the profile, root email, username, sign-in URL, and token URL. Password and TOTP changes do not change that key, so an existing token can still be reused.

Service-account entries use <dir>/service-account-v1/<hash>.json. Their SHA-256 key binds the auth kind, profile, client ID, fixed token URL, and client secret. Changing the secret selects a different entry. The cache stores neither the client secret nor Basic authorization headers. Old entries and issued tokens can remain after rotation.

The cache directory is created with mode 0700, and each token file with mode 0600; a pre-existing directory that group or others can access is refused.

One locked operation per credential set reads the cached token, logs in only if it is missing, expiring within 30 seconds, or was rejected by the server at least 30 seconds ago, and writes the result back, so two processes sharing one profile never log in with the same TOTP code. The lock is tried without blocking, then retried with backoff until the call's context ends; a lock file is never deleted, and a failed cache write after a successful IAM login still returns the fresh token. Service-account cache directory, read, and lock failures return vngcloud.ErrTokenCache, without falling back to an uncached exchange. A cache write failure after a successful exchange still returns the fresh token. On Linux, macOS, and the BSDs the lock uses flock; on Windows it opens the lock file with an exclusive share mode. A platform with neither locks within the process only, which still avoids duplicate logins from one process but not from several.

Clone this wiki locally