Privacy Policy

Last updated: 2026-10-01

This policy describes what data is processed when you visit byteflavour.dev and when you use the git forge at git.byteflavour.dev, and why.

Scope

This policy covers:

  • byteflavour.dev — this site: the blog and the Garden. Its public pages are generated in advance and served as files. Signing in is possible but never required to read anything. Sign-in, registration, the profile, organizations, the Cockpit and the chat talk to an interface under /api that runs on the same machine (referred to below as this site's server).
  • git.byteflavour.dev — a self-hosted Forgejo instance (a git forge) with user accounts.
  • sso.byteflavour.dev — the sign-in service that authenticates forge accounts and sign-ins on this site.
  • count.byteflavour.dev — the pageview-counting endpoint. Embedded on byteflavour.dev only, not on the forge.
  • inter.byteflavour.dev and rtc.byteflavour.dev — the chat on byteflavour.dev: the chat server and the service for calls. Described in the section The chat.

The identity provider at sso.byteflavour.dev also authenticates other self-hosted services that this policy does not cover; those have their own disclosures.

All of them run on the same machine, under the same controller. The difference between the blog and the forge is still substantial: the page you are reading processes almost nothing as long as you don't sign in; a forge with accounts necessarily processes more. Where the two differ, it is stated in the relevant section.

Data controller

The party responsible for all of the above is listed on the Imprint page. Privacy enquiries — including the data subject rights listed below — go to the email address given there. No data protection officer has been appointed; the thresholds in Art. 37 GDPR and § 38 BDSG are not met here.

Hosting

All of the services above run on a single server operated by Hetzner Online GmbH, in their Falkenstein/Vogtland data centre in Germany. Hetzner provides the machine; they do not access content as part of normal operation.

Server log files

Like effectively any web server, the reverse proxy in front of all of the above services logs basic technical information for every request: IP address, timestamp, requested path, HTTP status, referrer, and user-agent string. This applies to the blog and to the forge.

  • Purpose: operation, troubleshooting, and protection against abuse.
  • Legal basis: Art. 6(1)(f) GDPR — legitimate interest in operating the services securely and reliably.
  • Retention: the web server's access logs are kept on the machine for at most 7 days; anything older than 30 days is deleted in any case as well. The operating system's logs are discarded after 30 days. For analysis, the entries are copied into a log store and discarded there automatically after 30 days as well.
  • One-time codes: codes from confirmation and invitation links, and the identifiers with which GitHub or Codeberg send you back after signing in, are replaced by a placeholder before anything is written.
  • In backups: none. Neither the web server's access logs nor the operating system's logs are backed up.
  • Access: not public, not exported to any third party.

Git access over SSH is logged by the operating system in the same way (time, IP address, fingerprint of the key used). What is said above about the operating system's logs applies to those entries.

Logs of this site's server

For every request to /api, this site's server logs which interface was requested (without the values in the address), the result, how long it took and — if you are signed in — your account's identifier (a number, not your name). For organizations, the identifier of the organization and, where there is one, of the invitation are added; for the chat, the identifier of the device. Not logged are IP address, name, email address, passwords, codes or content. For troubleshooting, individual requests are additionally recorded as a trace, with the same details.

  • Purpose: operation and troubleshooting.
  • Legal basis: Art. 6(1)(f) GDPR — legitimate interest in operating the services securely and reliably.
  • Retention: 30 days in the log store and in the operating system's logs, traces 14 days. Not in backups.

Intrusion detection

An intrusion detection layer (CrowdSec) reads those same access logs and temporarily blocks suspicious IP addresses at the network level — for instance after repeated failed sign-in attempts. So that it recognises failed sign-ins on this site, this site's server marks its answer to a wrong name, a wrong password, a wrong code or a refused invitation, and likewise an answer it refuses because of too many attempts. The marker contains only "failed" or "throttled" — no account, no name. The IP address that goes with it is in the access log. What it processes is the IP address, along with the reason for the block and when it expires. These decisions are kept locally on the machine and expire on their own.

  • Legal basis: Art. 6(1)(f) GDPR — legitimate interest in defending against attacks.
  • Shared with a third party: this instance is enrolled in the community network run by CrowdSec SAS (France). That cuts both ways: it pulls blocklists of known attacker addresses from there, and it reports its own findings back. What is transmitted is the flagged IP address together with the detection scenario it triggered and a timestamp — not the content of your requests, not your account, nothing else. This only affects addresses that actually triggered a detection scenario; the IP address of an ordinary visit is not reported.
  • Location of processing: France, so within the EU.

The forge: accounts and content

This section applies to git.byteflavour.dev only. Reading the forge without signing in leaves nothing beyond the server logs described above.

Account data

An account on the forge stores: username, email address, display name, the time of registration and of the most recent sign-in, and an identifier for the authentication method the account uses. On top of that, whatever you add yourself: uploaded SSH and GPG keys, generated API tokens, avatar and profile details, and your settings (notification preferences, for example).

  • Purpose: running the account and attributing your contributions.
  • Legal basis: Art. 6(1)(b) GDPR — performance of the usage relationship you enter into by registering.

Content

Repositories, commits, issues, pull requests, comments, reactions, and attachments are stored for as long as they exist. Two things are easy to overlook about a git forge:

  • Public repositories are public. Content in a repository marked public is readable by anyone on the internet without signing in — including your username and your contributions. That is the point of the thing, but it is a publication.
  • Commits carry whatever you put in them. The name and email address in a commit come from your local git configuration, not from your account here. They are taken over verbatim and become part of the history. Changing git history after the fact requires rewriting it and force-pushing — that is true technically, regardless of what permissions you or I hold.

If you would rather avoid that: git lets you set user.email to an address that is not your real one.

Session cookies

The forge sets technically necessary cookies: a session identifier after sign-in, a token protecting against cross-site request forgery, and — if you choose it — a cookie for staying signed in. These are required for signed-in operation and are exempt from consent under § 25(2) TTDSG. They are not tracking cookies, and no third-party cookies are set.

Email notifications

The forge sends notifications (about issues, pull requests, or security events, for example) to the address on your account. Delivery goes through a self-hosted mail server on the same machine; the sender is forgejo@byteflavour.dev. No external email provider is involved. What your own email provider does with the delivered message is outside my control. Notifications can be switched off in your account settings.

Signing in

Signing in via sso.byteflavour.dev

The forge has no password registration of its own. Sign-in goes through a self-hosted identity provider at sso.byteflavour.dev, running on the same machine under the same controller. It processes username, email address, credentials (password hash and, where configured, a second factor), and sign-in logs. After a successful sign-in it passes on to the forge only what is needed to create and match the account: identifier, username, display name, and email address.

There is no local password registration; accounts are created through the identity provider or by an administrator. The external sign-in routes described below add the ability to register yourself using an account you already hold with another provider.

Signing in on byteflavour.dev

This site has a sign-in page of its own, at /auth/login. It uses the same accounts as the identity provider at sso.byteflavour.dev; you do not need to sign in to read anything here.

What happens when you sign in there:

  1. What you enter — your username or email address, and either a passkey confirmation or a password followed by a code from your authenticator app — is sent by your browser to this site's server.
  2. The server passes it straight on to the identity provider at sso.byteflavour.dev, which checks it. The server does not store your password, your code, or your passkey confirmation. While you are signing in, it records for at most 5 minutes which account is signing in.
  3. After a successful sign-in, the server keeps a session: the identifier of your account and of your organization, your username and display name, the session at the identity provider that goes with it and — once you open the chat — the identifier of your chat device. The session is kept on the server, not in your browser; your browser holds only a random identifier as a cookie (see Cookies on this site). The session ends when you sign out, and after 12 hours at the latest; the session at the identity provider and this browser's chat device end with it.
  4. For changes in your profile and in organizations, and for the Cockpit, the server acts on your behalf at the identity provider. To do so it obtains an authorisation for your account there and keeps it encrypted until it expires or your session ends.

To slow down password guessing, the server counts sign-in attempts: per IP address, failed steps and every lookup of an account name, each for 5 minutes; and per account, failed steps for one hour. The IP address is held in the counter in clear text, the account name only as a checksum. The counters are kept in a store on the server, survive a restart, and expire on their own after the time stated. They are not backed up.

  • Legal basis: Art. 6(1)(b) GDPR for the sign-in, the session and acting on your behalf, which happen only because you ask for them; Art. 6(1)(f) GDPR — legitimate interest in protecting accounts against guessing attacks — for the counters.

If you choose GitHub or Codeberg on that page, what is described under Signing in with an external identity provider applies; afterwards you return to the page you started from.

Creating an account on byteflavour.dev

Anyone can create an account here, at /auth/register, or through an invitation to an organization. You are not sent to the identity provider's own pages at any point; the form is on this site.

What is processed, and by whom:

  1. What you enter — the name you want to be known by, and an email address — goes to this site's server and from there straight to the identity provider at sso.byteflavour.dev, which is where the account is created straight away. While the registration is in progress, this site's server keeps its state: the identifier of the new account and of its organization, a checksum of the address, and which step you have reached; when registering with GitHub or Codeberg, also the address, name and username that provider reported. This state is kept for 70 minutes, or 72 hours and 10 minutes for an invitation, and is removed once the registration finishes. On the account at the identity provider, the server notes that the registration is not finished yet, and until when.
  2. The confirmation message is sent by the identity provider, not by this site, to the address you gave. It contains a code. This site never learns that code — it only passes on what you type, or what the link in the message brings along, and the identity provider decides whether the two match. The code is good for one hour, or 72 hours for an invitation; you can ask for a new one.
  3. How you will sign in is the last step, and it cannot be skipped: either a passkey, which never leaves your device and puts no secret anywhere, or a password together with a one-time code from an authenticator app. A password on its own is not accepted here.
  4. A registration that is not finished is deleted — together with the account at the identity provider. That happens one hour (72 hours for an invitation) after the last code was sent or, if the address has already been confirmed, after the confirmation — at the latest a few minutes after that.
  5. Registering with GitHub or Codeberg works too, and then there is no confirmation message and no second factor: that provider has already established who you are, and the link to them is what signs you in. What is transferred in that case is described in Signing in with an external identity provider. The name and email address that provider reports are filled into the form for you; you can change them before you finish.

What an account is worth on its own: an identity, and the signed-in area. No service is switched on by registering, and you cannot switch one on yourself: which services are open to you depends on your organization and on what the people responsible for it assign to you. The Cockpit shows you.

To keep the entrance from being used to make accounts in bulk or to have messages sent to an address that did not ask for them, the server limits how many registrations one IP address may start in an hour and how often one email address may be mailed in an hour. The counters hold the IP address in clear text and the email address only as a checksum, are kept in the same store as the sign-in counters, and expire after one hour. Requests beyond the limit are refused before the identity provider is contacted and before any message is sent.

  • Legal basis: Art. 6(1)(b) GDPR — the account is created because you ask for it, and the address is confirmed so that it is yours; Art. 6(1)(f) GDPR — legitimate interest in keeping the entrance usable — for the limits. Deleting unfinished registrations follows from the principle of keeping nothing longer than necessary.

Signing in with an external identity provider

You can also sign in with an account you already hold at GitHub or Codeberg. What is actually offered on the sign-in page at sso.byteflavour.dev, or on the sign-in page on byteflavour.dev, is what counts. The transfer described here happens only if you use one of those routes — it is tied to your choice, not to the mere presence of the button.

What happens if you sign in through one of these providers:

  1. You pick the provider at sso.byteflavour.dev or on the sign-in page on byteflavour.dev.
  2. The identity provider at sso.byteflavour.dev redirects your browser to that provider and acts as the requesting application towards it.
  3. You sign in at that provider, which asks you to consent to sharing your details.
  4. The provider returns your identifier, your username, and — depending on the provider and on what you release — your email address and display name.
  5. Those details are used to create or match your account at sso.byteflavour.dev.

Account creation and linking at sso.byteflavour.dev: the first sign-in through an external provider on the sign-in page of sso.byteflavour.dev automatically creates an account there. If the email address reported by that provider matches one on an account that already exists, the two are linked rather than a second account being created — the external route then becomes an additional way into your existing account. There is still no registration with a local password.

An account is not yet access: a successful sign-in creates an account with the identity provider only. Whether it lets you use any particular service reachable through it depends on that service — some require a separate authorisation on top. Without it, no data is passed to the service in question. Your account, along with the details taken from the provider, still exists at sso.byteflavour.dev regardless — including in the case where you end up able to use no service at all. You can ask for it to be deleted at any time; see Retention and deletion.

On byteflavour.dev, this site's server starts the route to the provider itself, through the identity provider at sso.byteflavour.dev. It therefore learns which provider you chose, and receives what that provider reports: your identifier and username there, your email address and your name. If that account at the provider is already linked to an account here, you are signed in; if it is not, you continue with a registration (see above), with those details filled in. You can link and unlink such routes in your profile. The forge, by contrast, only ever talks to sso.byteflavour.dev and does not learn which external provider you used, beyond an identifier for the sign-in route. The controller is the same person in all cases.

What reaches a third party: redirecting means your browser connects to that provider, which therefore learns your IP address, your user agent, and the fact that you are trying to sign in to this instance. The account details listed above are then received back from them.

  • Legal basis: Art. 6(1)(b) GDPR — the processing happens only if you actively choose this route, and is then necessary to create the account.
  • Transfers outside the EU: GitHub is based in and processes in the United States, so signing in through GitHub means a transfer to a third country within the meaning of Chapter V GDPR. Codeberg is run by a registered association based in Germany; no third-country transfer occurs there. If you would rather avoid one, Codeberg is the route without it.
  • Avoidable: these routes are alternatives, not requirements. If you would rather not use them, don't — the transfer then does not happen.
  • The providers' own policies: what they do on their side is governed by their own privacy policies, over which I have no influence.

Your profile

Signed in, you can look after your account yourself under "Profile": display name, first and last name, nickname and language, your email address, your password, passkeys and authenticator app, and linked routes through GitHub or Codeberg. This site's server writes every change on your behalf to the identity provider at sso.byteflavour.dev; it keeps none of it itself.

  • Confirmation before sensitive changes: anything that changes how you get into your account first asks for a fresh confirmation — with password and code, a passkey or a linked route. The server remembers for 5 minutes that you have confirmed. If confirming through GitHub or Codeberg takes you away from the page, your browser keeps the intended change — for a new email address, that address — in this tab's session storage and carries it out on your return, if that happens within 10 minutes; after that it is discarded.
  • New email address: the identity provider sends a code with a link to the new address. If you open the link without being signed in, sign in first and then open it again, or enter the code; the code is not carried over into other addresses in the process.
  • What is not possible: a route without which you could no longer get into your account cannot be removed. You cannot delete your account yourself here yet; write to me, see Retention and deletion.
  • Legal basis: Art. 6(1)(b) GDPR — you are managing your own account.

Organizations and invitations

Every account belongs to an organization. Signed in, you can create one of your own and invite others.

  • Creating: the organization is created at the identity provider with its name; the server also notes who created it and when.
  • Members: members see the display names of all members; whoever is responsible for the organization (owners) also see their usernames. Owners assign services to members. When someone leaves the organization, their assignments end.
  • Invitations: an invitation is a link that is valid for seven days. The server stores the organization, the role, who invited (identifier and display name) and the times, but the key in the link only as a checksum; the key itself is in the link after the # and reaches no server until you accept the invitation. Whoever accepts sees who invited them.
  • Limits: the server counts how many organizations and invitations a person or an IP address creates in an hour or in a day — with the account's identifier or the IP address in clear text, for one hour or one day respectively.
  • Legal basis: Art. 6(1)(b) GDPR — organizations and invitations exist because you create and accept them; Art. 6(1)(f) GDPR for the limits.

The Cockpit

The Cockpit shows you which services there are and which of them are open to you. For that, this site's server asks the identity provider what has been assigned to your organization and to you, and remembers the services' settings and the assignments to organizations for 5 minutes — without any details about you. The legal basis is Art. 6(1)(b) GDPR.

The chat

Only for people signed in on byteflavour.dev. If you never open the chat, none of what this section describes happens.

One server, one circle

The chat runs on a Matrix server that I operate at inter.byteflavour.dev, on the same machine as everything else here. I run it for byteflavour.dev itself and for those I invite to it: access is for those whose organization the chat has been opened to — that is my decision, not the individual's, and the Cockpit shows it. Everybody is on this one server, everybody on it is equal, and everybody's data is kept in the same place. Spaces arrange conversations; they are not a separate environment and they do not keep parties apart. The server exchanges messages with no other Matrix server.

Anyone who needs a separation that is technical rather than organisational needs a server of their own. This is not one.

The shared space is a place where people meet, and what is written there is seen by everybody in it. That follows from the door being open rather than from anything technical: a conversation of your own is the place for what is not for everybody.

For now the chat works in this browser. Using it from a separate Matrix app needs an authorisation that is not granted here, so access to the chat does not yet give you that.

What is open is open to everybody

A conversation is either open or reachable only by invitation; the list says which. An open conversation is listed in this server's directory, and anybody with an account here can find it and enter it — without asking anyone and without an invitation. Whoever creates such a conversation also decides whether somebody who arrives later can read what was said before they did.

You can leave a conversation at any time. An open one you can enter again yourself afterwards; one that requires an invitation will need a new one. In encrypted conversations you may find that what was written while you were away, or before you arrived, is no longer readable to you.

How you get into the chat

When you open the chat, this site's server issues a short-lived, signed statement of your account identifier and exchanges it with the chat server for a chat session. No password is sent. From then on your browser talks to the chat server directly; this site's server does not follow along.

The first time, an account is created on the chat server. Its identifier is the identifier of your account at sso.byteflavour.dev — a number, not your name. Operations set your display name there from the same account.

A chat session does not expire on the chat server by itself. It ends when you sign out of this site, when you end the device in the chat's settings, or on your next visit if your sign-in on this site has expired in the meantime. If your account is deleted, I deactivate your chat account too: all devices are signed out, signing in is no longer possible, display name and profile picture are removed, and you leave all conversations. What you have written stays visible to the other participants in those conversations; I remove individual messages on request.

What I can see — and what I cannot

Conversations are either end-to-end encrypted or not; the list of conversations shows which. That is the difference that matters:

encrypted conversationsunencrypted conversations
What is written, edits, pictures sentnot readablereadable
Sound and picture of callsnot accessibletechnically accessible, not recorded
Who is in which conversation and space, who wrote whenvisiblevisible
Names of conversations and spaces, display namesvisiblevisible
What a reply, a thread or a reaction refers to, and a reaction's charactervisiblevisible
Pinned messages (which ones), typing indicators, read receiptsvisiblevisible

The keys of encrypted conversations are created in your browsers and stay there. So that a new browser can reach your earlier conversations, the chat server keeps a backup of those keys — encrypted with your recovery key, which neither this site's server nor the chat server ever receives. If it is lost and you have no other browser that has already been let in, nobody can restore those conversations, me included.

You can let others see your read receipts, or not, in the chat's settings. A receipt that is not shown still reaches the chat server; it is just not shown to anyone else. The same goes for the typing indicator: turn it off and nobody is told that you are writing.

Your devices

Every browser you open the chat in is a device of its own to the chat server. It keeps an identifier for each, a name, when it last saw it and from which address. That is not a side effect but the foundation: without that distinction nobody could stay signed in, and end-to-end encryption would have nothing to encrypt for — keys belong to devices, not to accounts.

The name is given by this site the first time, from your browser's identification — "Firefox on Linux", say. No history, no version, no address; just enough to tell your own devices apart. You can change it whenever you like.

In the chat's settings you can see this list and end any device except the one you are using. It then loses its keys and can no longer read this account's encrypted conversations; your sign-in to this site stays as it is, and nothing changes at sso.byteflavour.dev. The device you are sitting at is ended by signing out of the chat.

One entry in that list is not a browser: a key holder your account keeps, so that keys still arrive while none of your browsers is open. Without it, everything said in that time would be unreadable. It stands in a section of its own, and can be neither confirmed nor ended.

Pictures and deleted messages

Before a picture leaves your browser, the browser removes everything that is not the picture: location, camera, timestamps. If it is wider than 800 pixels, the browser also sends a reduced preview along with it. In encrypted conversations the picture and its preview are encrypted in the browser before they are uploaded; the chat server holds only encrypted content that neither I nor a backup can open. In unencrypted conversations the picture is stored as it arrives; any signed-in person who knows its address can retrieve it — typically those who have already seen it in the conversation.

The chat server makes reduced copies of its own: of pictures from unencrypted conversations that arrived without a preview of their own, and of all profile pictures and pictures of conversations and spaces, in several sizes. It keeps them alongside the original. Profile pictures and pictures of conversations and spaces are never encrypted; your profile picture is seen by everyone you share a conversation with or who finds you in the directory.

When you delete a message, it disappears from the conversation. The chat server keeps the original for another seven days; during that time only the server's administration can retrieve it, not whoever manages a conversation or space. In encrypted conversations that original is encrypted too. When you delete a message with a picture, the picture, its preview and the server's copies stay there until I remove them — in unencrypted conversations still retrievable by the people named above, in encrypted conversations still unreadable. The same goes for a replaced profile picture. If you want them removed, write to me.

Search in the chat runs on the chat server and therefore only finds what was written in unencrypted conversations.

Notifications

Notifications while the chat is closed only exist if you turn them on in a browser. Then this happens:

  1. Your browser registers with its vendor's push service and receives a delivery address. The chat server stores that address and its keys so that it can notify you.
  2. When something new arrives, the chat server sends a message to a delivery service on the same machine, which encrypts it for your browser and delivers it through the vendor's push service. The push service does not see what is in it — only that your browser receives something, and when.
  3. The notification on your device names the conversation and who wrote — the same way in every conversation, so that its shape does not reveal whether a conversation is encrypted. It shows what was written only if you explicitly allow that in this browser, and never from encrypted conversations. That permission applies only to the browser you give it in: a lock screen belongs to a device, not to a person.

Which push service is involved is decided by your browser, not by me: for Chrome and other Chromium browsers Google, for Firefox Mozilla, for Safari Apple, for Edge Microsoft. Google, Apple and Microsoft process in the United States; registering with their push service is then a transfer to a third country within the meaning of Chapter V GDPR. If you want to avoid that, do not turn notifications on — the chat works without them.

Your settings for this — which conversations are muted, whether mentions notify you, and the words you want to be told about — are stored with your account on the chat server, so that they apply on all your devices. Those words are therefore readable to me. So is the list of people you ignore, with their names at the time you ignored them.

Calls

Calls run through a relay service (a so-called SFU, LiveKit) on the same machine, reachable at rtc.byteflavour.dev. In encrypted conversations sound and picture are end-to-end encrypted; the relay only forwards what it cannot open. In unencrypted conversations it forwards sound and picture unencrypted; nothing is recorded. For a call, the relay and the service that issues access process your account identifier, your device identifier, your IP address and details of your browser; there is no direct connection between participants.

The unread mark

While you are signed in and this browser holds a chat session, the menu at the top shows on the site's other pages too whether anything in the chat is unread. For that, your browser asks the chat server about every 30 seconds — only while the page is visible, and at most once per interval for all open tabs together. Each of these requests is an entry in the access log described under Server log files: with IP address and time, and so a trace of when you had the site open. The retention stated there applies to these entries.

The answer rests on a list the chat server keeps for your account: which messages notified you, when, and whether you have read them. It exists whether or not you have turned notifications on, holds only references to the messages, not their content, and is never cleaned up: it exists for as long as your chat account does.

What stays in your browser

The chat stores in your browser: the chat session, the keys for encrypted conversations, unfinished messages per conversation, the draft of a new conversation, invitations that could not be delivered yet (with the names of the people invited), whether anything is currently unread, which camera and microphone you chose for calls, and — if you turn notifications on — your choice of whether they may show text, along with the words a notification needs. These are not cookies, and they are sent to nobody except, where needed, the chat server itself. Signing out deletes all of it and ends the registration with the push service, and so does your next visit after your sign-in on this site has expired; the chat session is then also ended on the chat server. The only thing allowed to remain is which side panels you had open.

A counter for encryption

So that I notice when encrypted messages are unreadable more often than they should be, your browser occasionally reports three numbers to this site's server: how many messages it tried to decrypt, how many of those were unreadable, and how many became readable later. No conversation, no person, no message. So that nobody can flood this counter, this site's server counts the reports per IP address for 5 minutes, with the address in clear text.

Art. 6(1)(b) GDPR — the chat is a service you open and use yourself, and the processing described is necessary for it. That includes notifications and calls, which only happen when you choose them. For the counter, Art. 6(1)(f) GDPR — legitimate interest in encryption working reliably.

No third-party fonts

Typefaces are self-hosted, not loaded from Google Fonts or any other third-party font service. Loading fonts from a third party would send your IP address to that party on every page view — this site avoids that by design. That holds for the blog and for the forge alike.

Pageview stats (GoatCounter)

On byteflavour.dev only — the forge has no pageview analytics embedded at all.

This site measures aggregate pageviews through a self-hosted GoatCounter instance (reachable at count.byteflavour.dev). No cookie is set. To form a unique "visit" without a persistent identifier, GoatCounter briefly processes your IP address and User-Agent into a daily-rotating, salted hash — neither that hash nor the raw values (IP address, full User-Agent) are stored persistently.

What is stored, aggregated: the page viewed (the path only, without anything after ? or #), referrer, coarse browser/OS type, screen-size category, and coarse country of origin — never attributable to an individual visitor. The sign-in, registration and invitation pages are not counted, and neither is the signed-in area (chat, Cockpit, profile).

This data is never shared with or sold to any third party. The aggregate numbers are publicly visible on the Stats page, alongside a link to the technical interface schema (OpenAPI) that shows what this gateway exposes publicly (not to be confused with what GoatCounter itself processes on the backend — described above). The reasoning behind choosing GoatCounter is in this garden note.

There is no advertising and no other analytics tools or third-party trackers, on this site or on the forge.

Cookies on this site

As long as you don't sign in, the blog sets one cookie of its own:

  • Name: locale_pref
  • Purpose: remembers whether you're viewing the site in English or German, so you don't get redirected to a different language on your next visit.
  • Duration: 1 year.
  • Third parties: none. This cookie is never read by, or shared with, anyone but this site.

If you sign in or register, these cookies are added. Each contains only a random identifier; what belongs to it is kept on this site's server. All of them are restricted to this site (__Host-), are only sent encrypted, and — except for the last one — are unreadable to scripts on the page:

  • __Host-apix-attempt — a sign-in attempt in progress. It lasts 5 minutes and is removed once the attempt succeeds or ends.
  • __Host-apix-register — a registration in progress. It lasts 70 minutes, or 72 hours and 10 minutes for an invitation, and is removed once the registration finishes.
  • __Host-apix-idp — only for a route through GitHub or Codeberg: which route it is and where to return you to. It lasts 5 minutes and is removed on your return.
  • __Host-apix-session — your signed-in session (see Signing in on byteflavour.dev). It lasts as long as the session, 12 hours at most, and is removed when you sign out.
  • __Host-apix-signed-in — a marker that contains nothing but the value 1, no identifier and no name, and is the only one readable by scripts. It only tells the page that it is worth asking the server whether you are still signed in; visitors without it never cause that request. It lasts as long as the session and is removed with it.

None of these are read by, or shared with, anyone but this site.

Under German law (TTDSG §25(2)) and the EU ePrivacy Directive, cookies that are technically necessary for a service you explicitly use — like remembering a language choice, or keeping you signed in after you chose to sign in — don't require opt-in consent, unlike tracking or advertising cookies. That's the category all of these cookies fall into. The language cookie is set with a brief on-screen notice the first time, not silently, and not gated behind an "accept" click, since there's nothing optional to accept; the sign-in and registration cookies are set only because you start signing in or registering.

The forge's cookies are described under Session cookies above.

Backups

The machine is backed up nightly, encrypted, to Scaleway object storage in their Paris region (fr-par), France. The backup includes the databases of the forge, of the identity provider and of the chat server together with the chat's picture files and their copies — that is, account data and content; for the chat, as it is held on the server: encrypted conversations encrypted. Not backed up are the logs (see Server log files) and the store in which this site's server keeps sessions, registrations, invitations and counters. The data is encrypted before it leaves the machine; the key is not held by the provider, who therefore cannot read the backups.

  • Legal basis: Art. 6(1)(f) GDPR — legitimate interest in being able to recover from a failure.
  • Location: France, so within the EU. No third-country transfer.

One limitation I would rather state than gloss over: each backup is kept for about 90 days and then deleted. It sits in storage that technically prevents modification and deletion for 90 days — which is exactly the protection against ransomware and against accidental deletion, and it works against me too. In practice: if you ask for deletion, your account is deleted from the live systems, but the data remains in backups already written until that period expires, and is then deleted with the backup. During that time it is not used, not searched, and not read at all except in an actual restore. See the deletion section below.

Recipients

In summary — no third parties beyond these are involved:

RecipientWhat forWhat goes thereLocation
Hetzner Online GmbHhostingruns the machine; no content access in normal operationGermany
Scaleway SASbackupsencrypted backups, key stays hereFrance
CrowdSec SASintrusion detectionIP addresses that triggered a detection scenarioFrance
GitHubsign-inonly if you use that sign-in route — see aboveUSA
Codebergsign-inonly if you use that sign-in route — see aboveGermany
Your browser vendor's push service (Google, Mozilla, Apple, Microsoft)chat notificationsonly if you turn them on: an encrypted message and the fact that your browser receives it — see NotificationsUSA or EU, depending on the vendor

There are no ad networks, no analytics vendors, no content delivery networks, and no sale of data.

Retention and deletion

DataRetained
Web server access logs (incl. IP address)at most 7 days on the machine, 30 days in the log store
Logs of the operating system and of this site's server30 days; traces 14 days
Intrusion-detection blocking decisionsuntil the block expires
Account data (forge and sign-in)until the account is deleted
Unfinished registration, including the accountone hour (invitation: 72 hours) after the last code or the confirmation of the address
State of a registration in progress70 minutes, or 72 hours and 10 minutes for an invitation
Sign-in attempt in progress5 minutes
Sign-in session on byteflavour.devuntil you sign out, 12 hours at most
Authorisation to act on your behalfuntil it expires or the session ends
Counters for sign-in, registration, organizations and the encryption counter5 minutes, one hour or one day, depending on the counter
Invitations to an organizationseven days, or until accepted or withdrawn
Organizations and membershipsuntil they are deleted or you leave
Contributions in public repositoriessee below
Aggregate pageview statsindefinitely, but with no personal reference
Encrypted backupsabout 90 days, see above
Messages and pictures in the chat, including previews and copiesuntil they are deleted
Originals of deleted chat messagesseven days after deletion, see The chat
List of notifications in the chatas long as the chat account exists
Chat session and keys in the browseruntil you sign out, or your first visit after your sign-in has expired

An account on the forge can be deleted by you in your account settings, provided it has a password of its own on the forge — the deletion form asks for that password as confirmation. Accounts created through the identity provider have no such password; for those, the route is an informal message to the address on the Imprint page. The same goes for anyone else who would rather do it that way. Deletion removes account data, keys, tokens, and settings. An account for this site I delete at the identity provider on an informal message; a chat account that goes with it is deactivated, as described under How you get into the chat.

What deleting an account does not automatically remove: contributions that have become part of a shared project history — commits in a repository's history, and comments on issues or pull requests that others have replied to. On account deletion these are detached from the account and reassigned to an anonymous placeholder, but they remain in place; commits keep the authorship details written into them. If you want specific content removed beyond that, write to me — it is possible, but it is a manual intervention, and for git history it may mean a rewrite that does not reach other copies of the repository.

Your rights

Under the GDPR, you have the right to:

  • access the personal data processed about you (Art. 15),
  • rectification of inaccurate data (Art. 16),
  • erasure of your data (Art. 17),
  • restriction of processing (Art. 18),
  • data portability — receiving your data in a common format (Art. 20),
  • object to processing based on legitimate interest (Art. 21), and
  • lodge a complaint with a data protection supervisory authority (Art. 77).

An informal message to the address on the Imprint page is enough. To avoid handing data to the wrong person, I may ask you to confirm an access or deletion request about an account from the email address registered on it.

The competent supervisory authority, following the controller's location, is the Data Protection Commissioner of the State of Brandenburg (Die Landesbeauftragte für den Datenschutz und für das Recht auf Akteneinsicht Brandenburg). You are equally free to contact the authority where you live.

For the blog, these rights have little to act on as long as you don't sign in — one preference cookie and standard server logs is all there is. For the forge, and for signing in, they are substantial, and they apply in full either way.