1 Profiles and Credentials
Hirad edited this page 2026-08-14 09:18:17 +03:30

Profiles and Credentials

A profile combines non-secret network settings with either keyring-backed or file-backed credentials. The CLI and Python profile service use the same versioned TOML format.

Profile fields

Field Required Notes
Name Yes Starts with lowercase letter or digit; only lowercase letters, digits, _, and -
Type Yes lastfm, librefm, or gnufm
Username Yes Account used for history reads and submissions
API key Yes Stored in TOML as a non-secret field
API secret Yes Stored in keyring or TOML according to policy
Password or session key Yes Exactly one is normally chosen by the CLI; the core requires at least one
Hostname GNU.fm only Hostname without scheme, path, credentials, or whitespace
Proxy No HTTP(S) or SOCKS proxy; see Networks and Proxies

API keys and credentials must be obtained from the relevant service or GNU.fm instance.

Keyring storage

This is the default and recommended interactive configuration:

syncfm profile add personal \
  --type lastfm \
  --username alice \
  --api-key PUBLIC_KEY

The TOML document contains only non-secret settings and secret_storage = "keyring". A JSON credential payload is stored under keyring service syncfm and username equal to the profile name.

The host must provide a usable backend supported by Python's keyring package. Headless containers often do not; either provision a backend or deliberately use file storage with appropriate filesystem protection.

File storage

syncfm profile add ci-source \
  --type lastfm \
  --username ci-user \
  --api-key PUBLIC_KEY \
  --secret-storage file

File storage writes the API secret and password or session key directly into the TOML file. On POSIX, SyncFM writes the file atomically and sets mode 0600, but backups, mounted volumes, and copies can still expose it. Never commit this file.

An illustrative file-backed configuration is:

version = 1

[profiles.ci-source]
type = "lastfm"
username = "ci-user"
api_key = "PUBLIC_KEY"
secret_storage = "file"
api_secret = "SECRET"
session_key = "SESSION_KEY"

For keyring profiles, inline api_secret, password, or session_key fields are rejected. Unknown configuration versions are also rejected.

Non-interactive profile creation

The public options accept non-secret values, while secret prompts can read environment variables:

export SYNCFM_PROFILE_API_SECRET='...'
export SYNCFM_PROFILE_SESSION_KEY='...'

syncfm --config ./syncfm.toml profile add ci-target \
  --type librefm \
  --username ci-user \
  --api-key PUBLIC_KEY \
  --use-session-key \
  --secret-storage file

Unset those variables after use and configure the automation platform to mask them. An empty environment value is ignored and causes an interactive prompt.

Session-key authentication

Pass --use-session-key to prompt for SYNCFM_PROFILE_SESSION_KEY instead of SYNCFM_PROFILE_PASSWORD:

syncfm profile add personal \
  --type lastfm \
  --username alice \
  --api-key PUBLIC_KEY \
  --use-session-key

The underlying network factory passes either the existing session key or an MD5 password hash to pylast.

Replacing and removing profiles

profile add refuses duplicate names unless --force is used. Replacement supports moving between keyring and file storage and performs best-effort rollback if one part of the operation fails.

syncfm profile add personal ... --force
syncfm profile remove personal

Removing a keyring profile removes both its TOML entry and keyring secret. Removing a file profile removes its TOML entry, which contains its secret material.

Separate applications and files

Python applications can isolate credentials by selecting a custom keyring namespace:

from syncfm_core import create_profile_service

profiles = create_profile_service(
    "./profiles.toml",
    keyring_service="my-application-syncfm",
)

The CLI can select alternate profile files with global --config or SYNCFM_CONFIG_PATH.