Privacy
What this instance stores, in which form, and for how long. This page is generated from the server's running configuration, so the settings below are the ones actually in effect.
Current settings
@if(pv.ip_mode === 'hashed')IP addresses are logged, but only ever written to the database as HMAC-SHA256(ip, server_secret). The raw address is not persisted.@endif
@if(pv.ip_mode === 'raw')IP addresses are logged and written to the database in plain text.@endif
@if(pv.ip_mode === 'off')IP addresses are not stored. The only exception is brute-force protection: login attempts keep a keyed hash of the IP for {{ pv.ret.login }}, and a moderator ban stores the hash of the banned address.@endif
Retention
A cleanup job runs hourly and deletes or blanks data older than these periods.
user_ips rows deleted; IP columns on sessions, anonymous identities, uploads, comments, reports and ToS acceptances set to NULL.IP addresses
The client IP is taken from the first of CF-Connecting-IP, True-Client-IP, X-Client-IP, X-Real-IP, X-Forwarded-For (first entry) or the TCP peer address.
With IP logging on, the IP is recorded @if(pv.hash_ips)as an HMAC@else in plain text@endif in:
user_sessions.ip: updated on each request of a logged-in sessionuser_ips: one row per account and IP with first/last seen timeanon_identities.created_ip / last_ipandanon_activity_log.ipfor anonymous identitiesitems.uploader_ip,comments.ip,reports.reporter_ip
Hashing: HMAC-SHA256 keyed with a server-side secret, stored as 64 hex characters. The same IP always produces the same hash, which is what lets bans and rate limits work. Without the secret a hash can't be reversed or even recomputed, so a leaked database reveals no IP addresses.@if(pv.ip_secret_env) The secret is supplied through the server environment and is not part of the configuration file or database backups.@endif
Legally, hashed IPs are still pseudonymised personal data (GDPR Art. 4(5)), not anonymous: the operator, who holds the secret, can check whether a given IP matches a stored hash. That is how a ban recognises a returning address, and it is why hashed IPs are also subject to the retention period above.
@endifAlways, regardless of the logging setting: login and registration attempts store an HMAC of the IP in login_attempts for brute-force rate limiting, and a moderator ban stores the banned IP's hash in banned_ips.
Anonymous login (WebAuthn passkey)
No email, password or name is involved. Login as Anonymous creates a standard WebAuthn passkey in your authenticator (browser, OS, Bitwarden, iCloud Keychain, …).
Hardware security keys work too. A FIDO2 key such as a YubiKey (YubiKey 5 series, Security Key series) can hold the passkey: choose "security key" / "USB or NFC" when your browser asks where to save it, then plug in or tap the key. The private key is generated on the YubiKey and can never be exported from it, so the passkey is bound to that physical key and does not sync. The key may ask for its PIN and a touch. Since a lost key means a lost identity, register a second passkey (another YubiKey or a password manager) as a backup.
Registration
- The server sends creation options: relying party
{{ pv.domain }}, a random single-use challenge, algorithm ES256 (ECDSA P-256, COSE-7),attestation: "none", and a user handle of 16 random bytes namedanon@{{ pv.domain }}/ "Anonymous". Nothing about you goes into it. - Your authenticator generates a key pair. The private key never leaves the authenticator.
- The server verifies the response and stores: the credential ID, the public key (SPKI), the signature counter, and the authenticator's AAGUID (identifies the authenticator model, e.g. a password manager; with attestation "none" it is often all zeros; for a YubiKey it can reveal the key model, e.g. "YubiKey 5 NFC", but never its serial number).
- Your identity is derived from the credential ID:
SHA256:base64(SHA-256(credential_id)); the account name isanon_plus the first 8 hex characters of that hash (e.g.anon_1ad1e20c).
Login
The server issues a random single-use challenge; your authenticator signs it with the private key and the server verifies the signature with the stored public key. Up to 4 passkeys can be attached to one identity. If all of them are lost, the identity cannot be recovered: nothing else links it to you.
Device fingerprint
At anonymous login and when adding a passkey, your browser computes a device fingerprint used only for ban enforcement (so a banned user can't just create a new identity). It is not used for advertising or cross-site tracking.
Inputs, all read locally in your browser:
- WebGL: unmasked GPU vendor and renderer, 6 capability limits (max texture/renderbuffer size, vertex attribs, uniform/varying vectors, texture units)
- WebGPU adapter info (architecture, vendor, description), where available
navigator.hardwareConcurrency,deviceMemory,platform,maxTouchPoints- Screen width × height, colour depth, device pixel ratio
- Canvas 2D: checksum of a small rendered test image (text + shapes)
- Audio: sum of samples from an
OfflineAudioContextrendering a test tone through a compressor
The values are concatenated and hashed in the browser with SHA-256; only HW:<64 hex> is sent. The raw values never reach the server. The hash is cached in localStorage (f0ck_anon_hw_fp) and stored server-side in anon_identities.hw_fingerprint and the activity log, and compared against banned device hashes.
Anonymous activity log
anon_activity_log records these actions of anonymous identities: login/session handshake, favourite, unfavourite, favourites import. Each row holds the action, target item, time, identity fingerprint@if(pv.hw), device fingerprint@endif@if(pv.log_ips), IP@if(pv.hash_ips) (hashed)@endif@endif. It exists for moderation and ban cascades.
Sessions, cookies and browser storage
sessioncookie: 32 random bytes; the server stores only its SHA-256, so a database leak doesn't expose usable sessions. Flags:HttpOnly,SameSite=Lax@if(pv.https),Secure@endif.- Per session the server keeps: user agent string, creation time, last-used time, the last path requested, a CSRF token@if(pv.log_ips), and the IP@endif.
localStorage: UI preferences@if(pv.hw), and for anonymous users the device fingerprint hash@endif.f0ck_bannedcookie /f0ck_anon_tombstone: only set if you are banned, to show the ban notice.
Registered accounts: passwords are hashed with scrypt (random 16-byte salt, 64-byte key). The plain password is never stored.
Not collected
For anonymous identities: no email, real name, phone number or password@if(pv.anon)@if(!pv.hw), and no device fingerprint: device fingerprinting is disabled on this instance@endif@endif. No third-party analytics, trackers or ad networks are involved in authentication.
Questions? See About@if(mail) or write to {!! mail !!}@endif.