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.