<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://fortibus-consulting.com/insights/feed.xml" rel="self" type="application/atom+xml" /><link href="https://fortibus-consulting.com/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-07-27T12:53:39+02:00</updated><id>https://fortibus-consulting.com/insights/feed.xml</id><title type="html">Fortibus Consulting</title><subtitle>Fortibus Consulting B.V. builds and advises on privacy-first software: EU sovereign cloud infrastructure, mobile apps, and pragmatic engineering consultancy.</subtitle><author><name>Ryan</name><email>ryan@fortibus-consulting.com</email></author><entry><title type="html">SOVRAK: A Complete Platform for EU Startups That Want to Ship, Not Moonlight as Sysadmins</title><link href="https://fortibus-consulting.com/insights/2026/07/sovrak-starter-kit/" rel="alternate" type="text/html" title="SOVRAK: A Complete Platform for EU Startups That Want to Ship, Not Moonlight as Sysadmins" /><published>2026-07-24T00:00:00+02:00</published><updated>2026-07-24T00:00:00+02:00</updated><id>https://fortibus-consulting.com/insights/2026/07/sovrak-starter-kit</id><content type="html" xml:base="https://fortibus-consulting.com/insights/2026/07/sovrak-starter-kit/"><![CDATA[<p>If you’re building a startup in Europe and you’ve ever looked at your infrastructure bill and thought “I’m paying three US companies to hold my source code, credentials, and incident logs,” this is for you.</p>

<p>SOVRAK (the working name you’ll still see rendered as “Sovereign Stack” in the CLI’s own output) is a strongly opinionated CLI tool that generates a complete, pre-integrated internal operations platform – source control, CI/CD, identity management, monitoring, password management, documentation, email, and compliance – from a single interactive setup, so you skip the weeks of stitching these components together yourself. Everything runs on your own EU infrastructure, with no US-operated services and no US-jurisdiction operator anywhere in the chain – which is what takes it out of CLOUD Act reach.</p>

<p>Plenty of curated self-hosted lists end with an implied “good luck wiring it all together”; here the wiring (identity, routing, TLS, backups, compliance monitoring) is already done. You run the CLI, answer the prompts, deploy to a VM, and you’re working.</p>

<h2 id="what-you-get-out-of-the-box">What you get out of the box</h2>

<p>Here’s each piece of the stack and the problem it solves for you as a founder – not how it works internally, but why it’s there.</p>

<p><strong>Centralized identity and access control</strong> with Authentik. Every service in the stack sits behind single sign-on with mandatory multi-factor authentication. Hire someone, create one account, and they can access everything. When someone leaves, deactivate that account and they’re locked out immediately, across all services. Authentik also supports WebAuthn passkeys, the same tech behind Face ID, Touch ID, and Windows Hello, which are phishing-resistant by default. Access control at this level is a NIS2 Article 21 requirement, and you get it configured on day one.</p>

<p><strong>Source control</strong> with Gitea. A self-hosted Git platform that’s fast, lightweight, and familiar if you’ve used GitHub. Your code stays on your infrastructure, which matters both for sovereignty and for any customer who asks where their data pipeline source lives.</p>

<p><strong>Continuous deployment</strong> with Woodpecker CI. Push code to Gitea, Woodpecker picks it up via <span class="term-wrap"><span class="term" tabindex="0">webhook</span><span class="term-note" role="note"><span class="term-note-head">webhook</span><span class="term-note-body">An automatic ‘ping’ one app sends another the moment something happens - here, Gitea telling the CI system ‘new code was just pushed, go build it.’</span></span></span>
 and runs your pipeline. It authenticates through Gitea’s OAuth2 – and because Gitea federates to Authentik when you’ve selected it, you still get single sign-on, just one hop further out. Either way the OAuth app is created for you, so there’s no manual setup. If you’ve used Drone CI, Woodpecker will feel immediately familiar – it’s a community fork with the same YAML pipeline format. You have CI/CD from day one, instead of a “set up Jenkins” ticket that never quite reaches the top of the backlog.</p>

<p><strong>Password and credential management</strong> with Vaultwarden. A Bitwarden-compatible server that your entire team can use with the standard Bitwarden browser extension and mobile apps. Self-hosted means your credential vault isn’t sitting in a US data center. The admin panel is protected behind Authentik’s <span class="term-wrap"><span class="term" tabindex="0">forward auth</span><span class="term-note" role="note"><span class="term-note-head">forward auth</span><span class="term-note-body">A checkpoint at the front door: before a request reaches an app that has no login of its own, the gateway asks your central login service ‘is this person signed in?’ and only then lets it through.</span></span></span>
, and Vaultwarden handles its own encryption layer inside that – defense in depth without any extra configuration.</p>

<p><strong>Monitoring, metrics, and logs</strong> with Prometheus, Grafana, Loki, and Grafana Alloy. All four are configured and connected. Alloy automatically ships logs from every Docker container to Loki. Prometheus scrapes metrics. Grafana gives you dashboards. When something breaks at 2 AM, you have centralized logs and metrics in one place instead of SSHing into a server and tailing files. Grafana authenticates through Authentik, so it’s part of the same SSO umbrella. And those container logs aren’t a privacy blind spot: client IPs are truncated by the proxy before they’re ever written (a /24 for IPv4, /64 for IPv6 – data you never collected needs no erasure), everything is auto-deleted after 31 days by Loki’s retention, and logs are deliberately excluded from backups.</p>

<p><strong>Team documentation</strong> with Outline. A clean, fast wiki for your runbooks, architecture decisions, onboarding docs, and policies. File attachments are stored in Hetzner Object Storage (<span class="term-wrap"><span class="term" tabindex="0">S3-compatible</span><span class="term-note" role="note"><span class="term-note-head">S3-compatible</span><span class="term-note-body">Speaks the same storage language as Amazon S3, the de-facto standard for cloud file storage - so tools that expect S3 work with Hetzner’s EU storage unchanged.</span></span></span>
, EU-hosted), and the wiki is immediately available to your whole team through the same login they use for everything else in this stack.</p>

<p><strong>Email and newsletters</strong> with Listmonk. A self-hosted mailing list manager that sends through Brevo’s SMTP relay (a French company, free tier allows 300 emails per day, reasonable pricing for higher volume). Admin routes are protected by Authentik; public endpoints like unsubscribe links work without authentication. When you need to send product updates to early users or manage a waitlist, it’s already running.</p>

<p><strong>Governance, risk, and compliance</strong> with CISO Assistant. This is the piece most stacks leave out entirely, and it’s arguably the most valuable for an EU startup. CISO Assistant is built by Intuitem, a French company, and it handles compliance tracking across GDPR, NIS2, ISO 27001, DORA, and the Dutch BIO2 baseline. The SOVRAK CLI pre-configures it with the frameworks you select and generates a provisioning script, run automatically on first boot, that seeds your asset inventory, supplier register, applied controls, a baseline risk assessment, and per-framework audits directly into its database. Instead of staring at a blank GRC tool and wondering where to start, you get a pre-populated environment mapped to the specific components you’ve deployed.</p>

<p><strong>GDPR data-subject rights</strong> with the Erasix component. Where CISO Assistant tracks what you’re supposed to be doing, Erasix <em>does</em> it: right-to-erasure requests with cryptographically signed receipts, data portability exports, consent management with an embeddable banner, a tamper-evident audit trail, and retention enforcement. The redistributable SDK also ships a Loki provider (<code class="language-plaintext highlighter-rouge">Fortibus.Sovereignty.Loki</code>): if <em>your</em> application logs user emails, adding <code class="language-plaintext highlighter-rouge">.AddLoki()</code> folds those log lines into your app’s erasure and export answers – your app holds the email, so it can resolve which lines are the subject’s. Platform logs themselves are handled by minimization and retention instead (previous section), a deliberate choice: a receipt should never attest to a search the system can’t actually perform. Your users get a self-service privacy portal at <code class="language-plaintext highlighter-rouge">privacy.ops.yourdomain.eu</code> – they sign in with a verified-email link (no account on your ops stack needed), see their data, request an export or deletion, and download the result – while you get an operator API behind Authentik for handling requests that come in by email. The portal carries your branding and speaks your users’ languages from operator-supplied translation files. When a user invokes GDPR Article 17, the answer is a button, not a two-week scramble. (Curious how that button got built? The sovereignty build-diary series on this blog retraces the whole service, decision by decision.)</p>

<h2 id="the-integration-is-the-product">The integration is the product</h2>

<p>Any experienced developer could deploy each of these tools individually. The value of SOVRAK is that the weeks of integration work are already done.</p>

<p>Caddy sits in front of everything as a <span class="term-wrap"><span class="term" tabindex="0">reverse proxy</span><span class="term-note" role="note"><span class="term-note-head">reverse proxy</span><span class="term-note-body">A gatekeeper server in front of your apps: every web request hits it first, and it forwards each one to the right app - handling HTTPS and login checks in one place.</span></span></span>
 with automatic <span class="term-wrap"><span class="term" tabindex="0">TLS</span><span class="term-note" role="note"><span class="term-note-head">TLS</span><span class="term-note-body">The encryption behind the padlock in your browser - it scrambles traffic between visitors and your server so nobody in between can read it. (The ‘S’ in HTTPS.) Let’s Encrypt issues the certificates for free.</span></span></span>
 from Let’s Encrypt. Every service gets a subdomain of your ops domain – <code class="language-plaintext highlighter-rouge">auth.ops.yourdomain.eu</code>, <code class="language-plaintext highlighter-rouge">git.ops.yourdomain.eu</code>, <code class="language-plaintext highlighter-rouge">ci.ops.yourdomain.eu</code>, and so on. Caddy handles HTTPS termination, HTTP/3, and gzip/zstd compression for every service without any per-service configuration.</p>

<figure>
  <img src="/assets/images/diagrams/stack-topology.svg" alt="Caddy is the only public ingress, on ports 80 and 443, with Gitea SSH on 2222 as the one exception. Behind it sit the forward-auth gated hosts (vault, grafana, alerts, prometheus, ciso, docs, lists, sv), the self-authenticated services that would break under forward auth (git, ci, and the build agent's ci-grpc endpoint, gated by the agent secret), and the identity and public surfaces (auth, privacy). Everything runs on one bridge network." />
  <figcaption>Every service is a subdomain of your ops domain, and one proxy fronts all of them.</figcaption>
</figure>

<p>When Authentik is in the stack, everything ends up behind one login, though the mechanism differs by service. Gitea, Outline, and CISO Assistant sign in through Authentik via OIDC directly. Grafana auto-logs-in from the Caddy-verified session through a proxy header. Woodpecker authenticates through Gitea, which itself federates to Authentik. And underneath all of it, every operator-facing host sits behind a Caddy forward-auth gate – a valid Authentik session <em>in the <code class="language-plaintext highlighter-rouge">operators</code> group</em> is required before a request ever reaches the service, so having an account is not the same as having access. Vaultwarden and Listmonk rely on that gate exclusively; the services with sign-in of their own get it as a second lock on top. You don’t configure any of this – the CLI generates the right Caddyfile based on your component selection.</p>

<p>Backups run daily at 02:00 via a <span class="term-wrap"><span class="term" tabindex="0">systemd timer</span><span class="term-note" role="note"><span class="term-note-head">systemd timer</span><span class="term-note-body">Linux’s built-in scheduler - it runs a task on a clock (here, the backup every night at 2 AM) without anyone having to be there.</span></span></span>
. Every PostgreSQL database gets dumped, Vaultwarden’s SQLite database gets copied, and service data volumes get archived. Everything is compressed, encrypted, integrity-verified, then uploaded to Hetzner Object Storage with 30-day retention and automatic pruning – and the output includes a generated <code class="language-plaintext highlighter-rouge">restore.sh</code> so recovery is a script, not an archaeology project. The backup script uses a secure temp directory with trap-based cleanup, so even a failed backup doesn’t leave sensitive data on disk. And a monthly restore drill (the 5th, around 04:30) downloads the newest offsite backup and proves it actually restores – the first drill kicks off automatically right after your first successful upload, so you never sit on archives nothing has ever tested.</p>

<figure>
  <img src="/assets/images/diagrams/backup-pipeline.svg" alt="A systemd timer fires at 02:00. Every Postgres database is dumped, Vaultwarden's SQLite is copied and data volumes are archived. The result is compressed, encrypted, integrity-verified, and uploaded to EU object storage with 30-day retention." />
  <figcaption>None of this needs you awake for it, which is the only kind of backup that actually runs.</figcaption>
</figure>

<p>A weekly compliance monitor checks your Caddy configuration against a known-services list. If someone adds a new reverse proxy route – a new service that wasn’t part of the original deployment – the monitor detects it and sends an alert email with a compliance checklist. It’s a lightweight tripwire that keeps your infrastructure documentation honest as things evolve.</p>

<h2 id="compliance-is-built-in">Compliance is built in</h2>

<p>The stack treats the compliance paperwork as part of the deliverable.</p>

<p>There’s a compliance document that maps the deployed components to specific GDPR Article 32 and NIS2 Article 21 controls. Encryption in transit, MFA enforcement, centralized access control, audit logging, backup and recovery, network segmentation – each is documented with the specific technical measure in your stack that satisfies it.</p>

<p>CISO Assistant takes this further. The provisioning script creates entries for your deployed services as managed assets, registers your infrastructure vendors (Hetzner, Brevo) as suppliers with EU jurisdiction noted, and activates the compliance frameworks you selected during setup. When your first auditor asks “show me your asset inventory” or “where’s your supplier risk register,” you have a starting point that’s already populated with accurate data.</p>

<p>The documentation also includes incident response templates, CVE response SLAs (critical vulnerabilities within 24 hours, high within 7 days), a housekeeping calendar with weekly, monthly, quarterly, and annual tasks, and a subprocessor register that lists every external service with its EU jurisdiction and data processing purpose. This is the kind of documentation that takes weeks to write from scratch and that most startups don’t create until an auditor forces them to.</p>

<h2 id="who-this-is-for">Who this is for</h2>

<p>SOVRAK is for technical founders and small teams who want to move fast without outsourcing their infrastructure sovereignty. The ideal user is someone who’s comfortable with SSH and Docker but doesn’t want to spend weeks researching which identity provider integrates with which CI system and how to configure forward auth headers.</p>

<p>You need a single Ubuntu VM (Hetzner’s CX42 with 8 vCPU and 16 GB RAM is the recommended baseline, about €17/month at the time of writing – check Hetzner’s current pricing), a domain you control, a Brevo account for transactional email, and Hetzner Object Storage – every stack asks for both, because the encrypted nightly backups need somewhere offsite to go and the alerts need a relay (strictly, any S3-compatible object storage and any SMTP relay will do; Hetzner and Brevo are the tested defaults). The CLI handles the rest – dependency resolution, secret generation, configuration prompts, and file generation. Deploy with rsync and systemd, and you have a production-ready platform.</p>

<p>The CLI and the Erasix service are source-available under the Fair Core License: free to read, modify, and use internally, with each release converting to Apache-2.0 two years after it ships, and the SDK packages your own application links against are MIT. The components carry their own open-source or source-available licences (MIT for Gitea, AGPL-3.0 for CISO Assistant, Vaultwarden, and Listmonk, BSL for Outline). There’s no telemetry, no license keys, no phone-home, and no vendor lock-in beyond the infrastructure provider you choose – switching Hetzner for OVHcloud or any other EU provider is a DNS change and an rsync.</p>

<p>“We’ll figure out compliance later” is a perfectly good plan right up until an enterprise prospect sends over the security questionnaire. If you’re going to end up sovereign anyway, it’s cheaper to start there.</p>

<hr />

<p><em>Edited 2026-07-30.</em> Updated the monitoring and Erasix descriptions with how the stack handles personal data in logs: client IPs are truncated at the source and Loki’s 31-day retention auto-erases the rest, and the Erasix SDK gained a <code class="language-plaintext highlighter-rouge">Fortibus.Sovereignty.Loki</code> provider that applications can use to fold their own log lines into erasure and export.</p>

<p><em>Edited 2026-07-31.</em> Corrected the licensing description: the CLI and the Erasix service are source-available under the Fair Core License (each release converts to Apache-2.0 after two years), not MIT; the MIT carve-out covers the SDK packages your own application links against. Also corrected the CISO Assistant description: the provisioning script runs automatically on first boot and seeds directly into its database (there is no spreadsheet import in community CISO Assistant), and CISO Assistant signs in through Authentik via its own generated OIDC client rather than relying on the forward-auth gate alone.</p>

<p><em>Edited 2026-07-31.</em> The products now carry their working names: the stack is SOVRAK and the data-subject rights service is Erasix (the CLI’s own output still says “Sovereign Stack” for now). Also corrected the SSO description – the forward-auth gate fronts every operator host, not just Vaultwarden and Listmonk, which merely rely on it exclusively – added the newly published <code class="language-plaintext highlighter-rouge">prometheus.</code> host to the topology, noted the monthly restore drill, and clarified that Hetzner and Brevo are tested defaults for the object-storage and SMTP requirements, not the only options.</p>]]></content><author><name>Ryan</name><email>ryan@fortibus-consulting.com</email></author><category term="product" /><category term="sovereignty" /><category term="sovrak" /><category term="starter-kit" /><category term="eu-startups" /><category term="self-hosted" /><category term="compliance" /><summary type="html"><![CDATA[A source-available CLI that generates a production-ready infrastructure stack for European startups, with no US-jurisdiction operator in the chain: source control, CI/CD, identity, monitoring, and compliance, already wired together.]]></summary></entry><entry><title type="html">What the Law Wants From a Medication Logbook: Shipping a Health App in the US (and Maybe Canada)</title><link href="https://fortibus-consulting.com/insights/2026/07/what-the-law-wants-from-a-medication-logbook/" rel="alternate" type="text/html" title="What the Law Wants From a Medication Logbook: Shipping a Health App in the US (and Maybe Canada)" /><published>2026-07-21T00:00:00+02:00</published><updated>2026-07-21T00:00:00+02:00</updated><id>https://fortibus-consulting.com/insights/2026/07/what-the-law-wants-from-a-medication-logbook</id><content type="html" xml:base="https://fortibus-consulting.com/insights/2026/07/what-the-law-wants-from-a-medication-logbook/"><![CDATA[<p><em>Lou is our medication and care notebook for households – in development, currently
single-user-per-device, everything stored locally. This post is the legal homework we
did before deciding what it’s allowed to become. It is not legal advice; we are not
lawyers; the actual next step is paying someone who is. If you’re building a health
app and making decisions with real consequences, do that step too.</em></p>

<aside class="tldr"><div class="tldr-label">The 30-second version</div><p>A health app
that keeps all data on the user's device and never sends the developer a byte sits in a
surprisingly calm legal position in the US: HIPAA doesn't apply, breach rules have
nothing to bite, and the App Store privacy label can honestly say "Data Not Collected."
You still owe users a real terms-of-use and medical disclaimer, disciplined marketing
claims (the FDA classifies your <em>claims</em>, not your code), and a handful of
privacy features the law strongly implies. The moment you add sharing between people,
nearly every "not applicable" flips to "applicable" -- even if you encrypt everything
end-to-end and keep yourself unable to read it. The path through is consent: the person
the data is about decides who sees what, can see exactly who has access, and can revoke
it at any time. That's also, not coincidentally, the design we'd want as users.</p></aside>

<nav class="jump-menu"><div class="jump-menu-label">Jump to</div><ul><li><a href="#the-shape-of-the-problem">The shape of the problem</a></li><li><a href="#the-easy-path-one-user-one-device">The easy path: one user, one device</a></li><li><a href="#what-you-still-owe-even-on-the-easy-path">What you still owe, even on the easy path</a></li><li><a href="#sharing-where-the-easy-path-ends">Sharing: where the easy path ends</a></li><li><a href="#privacy-maximalism-doesnt-exempt-you">Privacy maximalism doesn't exempt you</a></li><li><a href="#and-canada">And Canada</a></li><li><a href="#the-path-well-probably-take-ask-the-person">The path we'll probably take: ask the person</a></li></ul></nav>

<h2 id="the-shape-of-the-problem">The shape of the problem</h2>

<p>Medication doses and health readings are about as sensitive as personal data gets.
The law agrees, loudly, in several jurisdictions at once. A US/Canada health app can
touch, depending on what it does: HIPAA, FDA device regulation, the FTC Act and its
Health Breach Notification Rule, Washington’s My Health My Data Act, Nevada SB 370,
California’s CMIA, more than a dozen comprehensive state privacy laws, COPPA, PIPEDA,
Quebec’s Law 25, and CASL. That list is why “we’ll figure out the legal stuff later”
is a plan with a short shelf life.</p>

<p>The useful discovery from working through all of it: the regimes differ in wording but
agree on one governing principle. <strong>The law protects the person the data is about, not
the person holding the phone.</strong> Keep those two identities the same and most obligations
stay quiet. Let them diverge – which is the entire premise of a caregiving app – and
obligations attach from every direction at once.</p>

<p>That principle splits the problem cleanly in two.</p>

<h2 id="the-easy-path-one-user-one-device">The easy path: one user, one device</h2>

<p>Lou today stores everything in a local database on the user’s device. There is no
account, no server, no analytics, no crash reporting, no networking code at all. We
never receive, transmit, or possess any user data. We arrived there as a privacy
conviction rather than a legal strategy, but it turns out to be the single most legally
consequential design decision available to a health app:</p>

<ul>
  <li><strong>HIPAA doesn’t apply.</strong> HIPAA is the most famous health-privacy law in America,
which is presumably why it gets credited with jurisdiction over everything up to and
including your neighbor asking about your knee. It actually binds <em>covered entities</em>
– providers, health plans, clearinghouses – and their business associates. A
direct-to-consumer app where the caregiver enters data that never leaves the device
makes the developer neither. (This changes the day a clinic or pharmacy starts
directing patients to your app as part of care – a trigger worth writing down now so
a future partnership doesn’t drift across the line unnoticed.)</li>
  <li><strong>The FTC’s Health Breach Notification Rule has nothing to bite.</strong> The rule covers
vendors of personal health records, and a breach concerns data the vendor holds or
discloses. Hold nothing, and there is nothing you <em>can</em> breach.</li>
  <li><strong>State health-privacy laws mostly aim past you.</strong> Washington’s My Health My Data
Act and its cousins target entities that collect and process consumer health data.
The strong reading is that a developer who never receives the data isn’t collecting
it – the consumer is processing their own data on their own device. These statutes
are new and aggressively worded, so this is a position to have counsel confirm rather
than a certainty, but the posture is about as good as postures get.</li>
  <li><strong>The App Store privacy label is simply “Data Not Collected.”</strong> A rare label, and
one that has to stay true at every release – more on that below.</li>
</ul>

<p>What “not applicable” does <em>not</em> mean is “nothing to do.” The easy path still has a
to-do list, and it’s worth being specific about it, because most of it is invisible in
screenshots.</p>

<h2 id="what-you-still-owe-even-on-the-easy-path">What you still owe, even on the easy path</h2>

<p><strong>A real terms-of-use and medical disclaimer.</strong> Less a formality than the legal
expression of what the product honestly is. Lou’s terms say, in plain English: this is
a record-keeping and reminder tool; it is not medical advice, not a dosing calculator,
and not a guarantee that any reminder arrives on time; everything it shows – “ready,”
countdowns, progress rings – is arithmetic on the schedule <em>you</em> entered; and if the
app and the medication label ever disagree, <strong>the label is right and the app is
wrong.</strong> Users accept this at first run on a screen that can’t be dismissed and can’t
be agreed to without scrolling to the end, and the accepted version and timestamp are
recorded. Delivery of reminders gets its own honest paragraph, because iOS genuinely
cannot promise a notification arrives – Focus modes, battery conditions, and the
operating system all get a vote – and a terms document that pretends otherwise would
be the deceptive claim the FTC actually enforces against.</p>

<p><strong>Marketing discipline, because the FDA classifies claims, not code.</strong> Most of Lou
sits squarely in the FDA’s stated low-risk categories: medication logs, adherence
tracking, user-configured reminders, symptom journaling. The gray zone is that Lou
doesn’t just log – it shows whether the minimum interval and daily maximum <em>you
entered</em> are currently satisfied. Described one way, that’s an automated version of the
paper log every caregiver already keeps. Described another way – “prevents
double-dosing,” “keeps your family safe” – it’s a safety device, and safety devices
are regulated. Same binary, different product, and the difference is the verbs. So the
rule we hold ourselves to, in the App Store listing and everywhere else: Lou <em>tracks,
logs, reminds, and organizes</em>. It does not <em>prevent, protect, ensure,</em> or <em>decide</em>.
(You may now appreciate the lawyerly caution with which this very paragraph is
written. Blog posts are marketing copy too.)</p>

<p><strong>Sample data curation, of all things.</strong> Our demo household used to take insulin. It
was a perfectly good demo medication apart from the part where it’s a high-alert drug
whose mistimed dose has real consequences – exactly the wrong screenshot to hand a
regulator or an App Review team wondering whether you’re a dosing calculator. The demo
family now enjoys robust over-the-counter health.</p>

<p><strong>Apple’s own layer.</strong> The App Store has its own quasi-regulatory regime: a privacy
manifest declaring which sensitive APIs you use and why (missing one is
submission-blocking), an export-compliance declaration, an honest answer to the
medical-content age-rating questions, and Guideline 1.4.2, which restricts drug dosage
calculators to drug manufacturers, hospitals, universities, health insurers, pharmacies,
and other approved entities. “When can the next dose be
taken” is dosage-<em>adjacent</em>, so the review notes explaining what the app is and isn’t
get written with the same care as the terms. And the license texts for open-source
dependencies need a screen of their own – the least glamorous compliance artifact,
and among the easiest to forget.</p>

<p><strong>Features the law strongly implies.</strong> Some requirements arrive dressed as product
work: an optional app lock, because a household device is shared by definition and
health data deserves a biometric check; a discreet-notifications option, because
even “Time for Pat to take cetirizine” on a lock screen is a health-data disclosure
to whoever’s standing nearby; a true “erase all data” action, because soft-delete
tombstones that linger forever make the word “delete” quietly dishonest; and
suppressing the “ready” arithmetic entirely if the database ever fails open in a
degraded state, because dose math over missing history is worse than no answer.</p>

<p><strong>And the honest big one: liability.</strong> For a caregiving app, the realistic worst case
isn’t a fine. It’s a family harmed after relying on the app, followed by perfectly
ordinary negligence claims. The mitigations are unglamorous: the disclaimer users
actually read, engineering rigor around exactly the failure modes that matter (stale
“take” buttons, duplicate recording, clock changes), and a test suite that pins each
one. A test suite is not usually a legal document. Ours may someday be read by someone
billing by the hour, as evidence of a standard of care. We write it accordingly –
and, on advice we’d give anyone: form the legal entity and have the insurance
conversation <em>before</em> public distribution, not after.</p>

<p>One more wrinkle, because Fortibus is an EU company: GDPR follows the developer’s
establishment, not the users’ location. It stays quiet today only because no personal
data reaches us at all – but the moment any does, GDPR applies in full even with zero
EU users. For us the “no data leaves the device” line isn’t just a promise to users;
it’s the load-bearing wall in two legal systems at once.</p>

<div class="planned">
  <p class="planned-label">Planned -- not yet built</p>

  <h2 id="sharing-where-the-easy-path-ends">Sharing: where the easy path ends</h2>

  <p>Everything above describes a calm, well-understood position – and it describes Lou
as it exists. What follows does not exist yet: it’s the legal homework for the feature
everyone asks for, the one the entire app was built around: households. Two parents
recording a child’s doses on two phones. An adult coordinating a parent’s medications
with a sibling. This is the actual shape of caregiving, and supporting it would
require data to move between people.</p>

  <p>The moment it does, the governing principle bites. The account holder and the data
subject diverge – the person tapping “share” is not the person the medication list
describes – and nearly every “not applicable” above flips:</p>

  <ul>
    <li><strong>The Health Breach Notification Rule wakes up</strong>, and its definition of breach
includes <em>unauthorized disclosure</em>, not just intrusion. Read that twice: a consent
screen with a defect – a share that went further than the user validly authorized –
is a reportable breach event with a 60-day notification clock, no hacker required.</li>
    <li><strong>Washington’s My Health My Data Act</strong> demands separate opt-in consent for
collection and a <em>distinct, specific authorization</em> for sharing – one bundled
“I agree” covering both is non-compliant on its face – and it comes with a private
right of action.</li>
    <li><strong>California’s CMIA</strong> expressly covers consumer software “designed to maintain
medical information,” with statutory damages.</li>
    <li><strong>Comprehensive state privacy laws</strong> treat health data as sensitive personal
information: opt-in consent, documented risk assessments.</li>
    <li><strong>COPPA</strong> enters conditionally, since households contain children.</li>
    <li>And the FTC’s most reliably enforced rule stands over all of it: no third-party
analytics, advertising, or attribution SDK may ever receive health data or anything
derived from it. The GoodRx, Premom, and BetterHelp actions all ran on exactly that
fact pattern. Lou satisfies this one by the elegant
mechanism of containing no such SDKs to begin with.</li>
  </ul>

  <h2 id="privacy-maximalism-doesnt-exempt-you">Privacy maximalism doesn’t exempt you</h2>

  <p>Here’s the part we found genuinely humbling. Our instinct for sharing is maximal
privacy: end-to-end encryption, keys generated and held on users’ devices, content
keys wrapped per recipient so that what someone can <em>see</em> is bounded by what they can
<em>decrypt</em> – and the operator (us) unable to read anyone’s health data, ever, by
construction. That is the single highest-leverage decision in the whole design: if the
server holds no plaintext, a server compromise is substantially not a disclosure, and
the public privacy claim survives contact with reality.</p>

  <p>We assumed, briefly, that this would also make most of the legal work fall away. It
does not. It changes <em>which</em> work remains:</p>

  <ul>
    <li><strong>An authority model.</strong> Before anyone shares a child’s or a parent’s data, the
system has to record on what basis they’re entitled to manage it at all – self,
parent or guardian of a minor, healthcare power of attorney – as an explicit, typed
attestation, not a line buried in the terms. The app can’t verify the claim and must
never pretend to; the legal function is an identified person making an identified
representation. But the record of who attested what, when, under which exact wording
has to be reconstructible years later.</li>
    <li><strong>Authorization per recipient, per scope.</strong> Sharing consent is a discrete,
affirmative act, separate from onboarding and separate from collection consent –
naming the recipient, the data categories, the purpose, and how to revoke. Adding a
recipient or widening their access requires a new authorization. Narrowing doesn’t.</li>
    <li><strong>Scope enforced by cryptography, not UI.</strong> “The app doesn’t show it to them” is a
filter. “They can’t decrypt it” is a boundary. Regulators, it turns out, can tell
the difference.</li>
    <li><strong>Revocation that means something.</strong> Revocable at any time, effective immediately,
keys rotated so old material doesn’t decrypt new data – and <em>honest</em> about its
limits, because an offline device can’t be reached and a screenshot can’t be
recalled. “Deleted everywhere instantly” would itself be a deceptive claim. The
legally safe sentence is also the true one: best effort, clearly described.</li>
    <li><strong>An audit log that works under encryption.</strong> The system must be able to answer,
years later and without reconstruction: <em>who could see what, when, on whose
authority</em> – about content we’ve deliberately made ourselves unable to read. So the
log records grants, scopes, attestations, revocations, key rotations, and access
events – metadata, never content – tamper-evident, retained past statutory
limitation periods, and visible to the data subject as an access history of their
own records. Keeping meticulous records about data you cannot read is the kind of
requirement that sounds paradoxical right up until you imagine the family-court
subpoena.</li>
    <li><strong>Notification at grant time.</strong> The person whose data is being shared (or their
representative) hears about it when the share is created, not when it’s first used.
Silent grants are the precise mechanism by which a family dispute becomes
litigation.</li>
    <li><strong>Recovery that doesn’t quietly defeat the whole thing.</strong> An account-recovery flow
that lets the operator restore plaintext is an E2EE system with a hole in it, and
every public claim made in reliance on the encryption goes down with it.</li>
    <li><strong>And a documented risk assessment before launch</strong> – required by several state
laws and, if Quebec is ever in scope, mandatory before deployment.</li>
  </ul>

  <p>None of this made us reconsider the privacy stance. It did permanently cure us of the
idea that privacy-by-design is a <em>shortcut</em>. It’s the right wall to build; it is not a
door out of the building.</p>

</div>

<h2 id="and-canada">And Canada</h2>

<p>We’d like Lou to work in Canada – the honest scope today is “possibly Canada,”
and here’s the short version of why it’s its own decision rather than a checkbox.
PIPEDA requires express consent for sensitive data, which health data always is –
directionally similar to the US state laws, so a design that clears Washington’s bar
travels reasonably well. Quebec’s Law 25 goes further: a privacy impact assessment
<em>before</em> deployment, privacy-by-default as a legal requirement rather than a design
preference, explicit consent, and its own breach regime. And CASL puts the
notification messages themselves on the checklist – its core rules cover commercial
electronic messages, and whether the email that says “you’ve been given access to
Emma’s readings” counts as one is a question a CASL analysis has to answer, not an
assumption to make. This is honestly rather sensible; it is also one more thing.
Health Canada’s software-as-medical-device
rules would need the same claims-discipline analysis we did for the FDA before any
launch there. Canada is on the list. It is not a footnote to the US launch, and we
won’t treat it as one.</p>

<div class="planned">
  <p class="planned-label">Planned -- not yet built</p>

  <h2 id="the-path-well-probably-take-ask-the-person">The path we’ll probably take: ask the person</h2>

  <p>So, knowing all of that – what will we actually do? Plans, not promises: single-user,
local-only Lou is the product that’s shipping, sharing has no date, and the technical
backend design isn’t settled. But the direction has been fixed for a while, because
every line of the analysis above points at the same door:</p>

  <p><strong>Get permission from the person the data is about, and mean it.</strong></p>

  <p>Concretely, the sharing model we’re designing toward:</p>

  <ul>
    <li><strong>You invite; nothing is shared by default.</strong> Sharing is initiated by the user, per
person, as a deliberate act – never an account setting that quietly applies to
everything.</li>
    <li><strong>You control visibility, granularly.</strong> A recipient sees the subset you chose –
which household member, which categories – starting from the minimum, expanding
only by your explicit say-so.</li>
    <li><strong>You can see exactly who has access.</strong> A plain-language list, at any time: who,
to what, since when, on whose authority.</li>
    <li><strong>You can revoke anyone, at any time.</strong> Effective immediately, keys rotated, the
recipient’s device told to delete its copy – described to you with best-effort
honesty, not marketing absolutes.</li>
    <li><strong>We can’t read any of it.</strong> End-to-end encrypted, keys on your devices, and our
inability to access your health data preserved as deliberately as the data itself.
The same property that has been Lou’s whole personality since the first commit,
carried into the one feature that most tempts an app to abandon it.</li>
  </ul>

  <p>There’s one more thing the legal analysis handed us, and it’s the practical insight
this whole exercise was worth: almost all of the authority-model complexity exists
only where the account holder and the data subject <em>diverge</em>. Where they’re the same
person – you, sharing your own medications with your spouse or the babysitter – the
authority question answers itself, and everything else (granular consent, scoped
grants, revocation, audit) still applies but is <em>buildable</em>. That’s a viable first
slice: start where consent is simplest and the law is satisfiable, design the data
model for the split from day one, and bring in proxy-managed subjects – the child,
the aging parent – once the authority model has been through counsel. The phase line,
usefully, was drawn for us by the law itself.</p>

</div>

<p>The quiet punchline of the whole exercise: the most private design and the legally
lightest design turned out to be the same design, and it <em>still</em> takes this much
work to do properly. That asymmetry explains a lot about the health-app market –
door number three, the one where you bolt on an analytics SDK and monetize the
“engagement,” is cheaper right up until the FTC explains otherwise. We’d rather do
the homework. The label is right and the app is wrong; the law, for once, mostly
agrees with the ethos.</p>

<hr />

<p><em><a href="/products/lou/">Lou</a> is in development for iPhone and iPad. If you’d like to hear
when it’s available, or you’re interested in early testing,
<a href="mailto:ryan@fortibus-consulting.com">get in touch</a> – we’d love a few households who care
about this as much as we do.</em></p>

<p><em>Edited 2026-07-24.</em> Two corrections: the App Store rule for drug dosage calculators is Guideline 1.4.2, not 1.4.3, and its allowed list is broader than we first wrote (drug manufacturers, hospitals, universities, health insurers, pharmacies, and other approved entities). Also updated the count of comprehensive state privacy laws, which has grown well past half a dozen.</p>

<p><em>Edited 2026-07-27.</em> The sections on multi-person sharing and end-to-end encryption are now marked as planned – they describe a design we’re working toward, not features of the shipping app, and the surrounding prose has been adjusted to match. Three smaller fixes: Lou is named in honour of the author’s daughter, not for the households feature; the lock-screen notification example now uses an over-the-counter medication, consistent with the demo-data curation described above it; and the CASL sentence is hedged, since whether an access-notification email is a commercial electronic message is a question for analysis rather than a given.</p>]]></content><author><name>Ryan</name><email>ryan@fortibus-consulting.com</email></author><category term="product" /><category term="health" /><category term="lou" /><category term="health-apps" /><category term="compliance" /><category term="hipaa" /><category term="fda" /><category term="ftc" /><category term="privacy" /><category term="e2ee" /><category term="pipeda" /><category term="consent" /><summary type="html"><![CDATA[Lou keeps medication doses and health readings on one device, which turns out to be the legally easy path. Here's what the law asks of a single-user health app in the US and Canada, why the multi-person sharing we're designing toward would change everything even with maximal privacy -- and the consent-first path we'll probably take.]]></summary></entry><entry><title type="html">EU SaaS Compliance on Hetzner: What the Law Actually Requires</title><link href="https://fortibus-consulting.com/insights/2026/07/eu-saas-compliance-on-hetzner/" rel="alternate" type="text/html" title="EU SaaS Compliance on Hetzner: What the Law Actually Requires" /><published>2026-07-09T00:00:00+02:00</published><updated>2026-07-09T00:00:00+02:00</updated><id>https://fortibus-consulting.com/insights/2026/07/eu-saas-compliance-on-hetzner</id><content type="html" xml:base="https://fortibus-consulting.com/insights/2026/07/eu-saas-compliance-on-hetzner/"><![CDATA[<p>You’re an EU founder. Your SaaS runs on Hetzner. You store user email addresses, process user data as part of the product, and send transactional and product emails. What does EU law actually require of you?</p>

<p>This post gives concrete answers: which articles apply, what they oblige you to do, and what to put in place. It skips edge cases that don’t apply to you, and it won’t tell you to “consider engaging a DPO” unless you actually need one.</p>

<blockquote>
  <p><strong>Not legal advice.</strong> I am not a lawyer. Nothing in this post constitutes legal advice, and you should not rely on it as such. This is my personal reading and interpretation of publicly available law and official guidance, informed by what regulators, legal commentators, and practitioners have published, but filtered through a non-lawyer’s understanding. EU data protection law is complex, national implementations vary, and your specific situation may have details that change the analysis entirely. If you are making compliance decisions with real legal or financial consequences, consult a qualified data protection lawyer or DPO in your jurisdiction.</p>
</blockquote>

<aside class="tldr"><div class="tldr-label">The 30-second version</div><p>If you read nothing else: sign a data-processing agreement with Hetzner and with an EU-incorporated email provider; write down your lawful basis for each thing you do with user data; publish a privacy notice and link it at signup; keep a short record of processing (a spreadsheet); encrypt the disk with a key Hetzner doesn't hold, and write your security measures down; make sure you can export and delete one user's data on request; and know which authority to notify within 72 hours of a breach. That's the paperwork, and it is smaller than you have been led to believe. The harder half is being able to actually <em>do</em> the things those documents promise -- which is a build, not a filing exercise. The rest of this post is the detail behind each step, and the <a href="#the-actual-checklist">full checklist</a> is at the bottom.</p></aside>

<nav class="jump-menu"><div class="jump-menu-label">Jump to</div><ul><li><a href="#what-you-are-under-gdpr">What you are under GDPR</a></li><li><a href="#the-lawful-basis-for-each-processing-activity">Lawful basis for each activity</a></li><li><a href="#the-dpa-with-hetzner">The DPA with Hetzner</a></li><li><a href="#the-dpa-with-your-email-provider">The DPA with your email provider</a></li><li><a href="#privacy-notice-under-article-13">Privacy notice (Article 13)</a></li><li><a href="#data-subject-rights-you-must-handle">Data subject rights</a></li><li><a href="#records-of-processing-activities">Records of processing (ROPA)</a></li><li><a href="#security-measures-under-article-32">Security measures (Article 32)</a></li><li><a href="#breach-notification-under-article-33">Breach notification (Article 33)</a></li><li><a href="#do-you-need-a-data-protection-officer">Do you need a DPO?</a></li><li><a href="#does-nis2-apply">Does NIS2 apply?</a></li><li><a href="#what-you-dont-need">What you don't need</a></li><li><a href="#the-actual-checklist">The actual checklist</a></li></ul></nav>

<h2 id="what-you-are-under-gdpr">What you are under GDPR</h2>

<p>You are a <strong>data controller</strong> under <a href="https://gdpr-info.eu/art-4-gdpr/">GDPR Article 4(7)</a>. You determine the purposes and means of processing your users’ personal data. This is not optional: the classification follows from the facts, not from what you put in a privacy policy.</p>

<p>Your users’ email addresses are personal data under Article 4(1). Everything you do with them – collecting, storing, using them to send emails, sharing them with a third-party email provider – is “processing” under Article 4(2). GDPR applies to all of it.</p>

<p>Hetzner and your email service provider are <strong>data processors</strong> under Article 4(8). They process personal data on your behalf, under your instructions. This has a specific legal consequence covered below.</p>

<figure>
  <img src="/assets/images/diagrams/controller-processor.svg" alt="Your users are the data subjects. You are the data controller under Article 4(7). Hetzner and Brevo are processors under Article 4(8), acting on your instructions, and each relationship needs a DPA under Article 28." />
  <figcaption>The obligations point at you, and stay there. A processor can carry out the work, but it cannot carry the duty.</figcaption>
</figure>

<h2 id="the-lawful-basis-for-each-processing-activity">The lawful basis for each processing activity</h2>

<p><a href="https://gdpr-info.eu/art-6-gdpr/">GDPR Article 6</a> requires a lawful basis for every processing activity. You need to identify one for each distinct thing you do with user data. Guessing at a single catch-all basis is a common mistake. At a glance:</p>

<table>
  <thead>
    <tr>
      <th>What you’re doing</th>
      <th>Lawful basis</th>
      <th>Separate consent?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Running the account, authenticating, delivering the service</td>
      <td>Art 6(1)(b) - contract</td>
      <td>No</td>
    </tr>
    <tr>
      <td>Transactional email (password reset, receipt, alerts)</td>
      <td>Art 6(1)(b) - contract</td>
      <td>No</td>
    </tr>
    <tr>
      <td>Product email about a feature they already use</td>
      <td>Art 6(1)(f) - legitimate interests</td>
      <td>No (document a brief LIA)</td>
    </tr>
    <tr>
      <td>Marketing / promotional email</td>
      <td>Art 6(1)(a) - consent + ePrivacy</td>
      <td><strong>Yes - prior opt-in</strong></td>
    </tr>
  </tbody>
</table>

<p>The detail behind each row:</p>

<p><strong>Account creation and service delivery.</strong> Your users give you their email address to create an account and use the product. Processing this data to operate the account, authenticate the user, and deliver the service they signed up for is covered by Article 6(1)(b): processing is necessary for the performance of a contract to which the data subject is party. No consent needed. No separate opt-in. They accepted terms and signed up; that’s the contract.</p>

<p>This basis covers: storing the email address, using it for login/authentication, storing whatever data they create or upload as part of using the SaaS, and using their data to provide the features they’re paying for.</p>

<p><strong>Transactional emails.</strong> Emails sent because the user took an action or something happened to their account – password reset, email verification, subscription renewal confirmation, payment receipt, alert that their data export is ready – are covered by Article 6(1)(b) for the same reason. These emails are part of delivering the service. No separate consent, no opt-in checkbox.</p>

<p><strong>Product emails.</strong> This is the muddy one. Emails about your product – release notes, feature announcements, tips for using the service – sit at the boundary between Article 6(1)(f) (legitimate interests) and regulated marketing communications.</p>

<p>Article 6(1)(f) allows processing where it is necessary for the purposes of legitimate interests pursued by the controller, provided those interests are not overridden by the interests or fundamental rights of the data subject. For an existing customer relationship, sending relevant product communications about the service they’re actively using is generally supportable under legitimate interests. You should document a brief legitimate interests assessment (LIA): not an elaborate document, but a record that you considered the three-part test: purpose test (is the interest legitimate?), necessity test (is processing necessary?), balancing test (do the user’s interests override yours?). The EDPB’s <a href="https://www.edpb.europa.eu/our-work-tools/documents/public-consultations/2024/guidelines-12024-processing-personal-data-based_en">Guidelines 1/2024 on legitimate interests</a> walk through this test in detail and are the authoritative reference. The ICO’s <a href="https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/lawful-basis/legitimate-interests/">legitimate interests guidance</a> is more concise and practical as a first read, despite being UK-focused; the three-part test is identical.</p>

<p>This does not extend to promotional emails about other products, upsell campaigns, or anything that crosses into commercial marketing.</p>

<p><strong>Marketing emails.</strong> If you send promotional emails – discount offers, cross-sell campaigns, affiliate promotions – you need explicit prior consent under both GDPR Article 6(1)(a) and the <a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32002L0058">ePrivacy Directive (Directive 2002/58/EC)</a>, Article 13. This means an opt-in at the point of collection, separate from terms of service acceptance, and a genuine choice. Pre-ticked boxes are not valid consent under <a href="https://gdpr-info.eu/recitals/no-32/">GDPR Recital 32</a>.</p>

<p>The practical line: “here’s what’s new in the product you use” = legitimate interests. “Here’s a special offer on our premium plan” = consent required. Most product emails from a SaaS to an active user are defensible as legitimate interests. Treat anything that could be read as a sales pitch with the consent standard.</p>

<p>One narrow exception is worth knowing before you conclude that every promotional email needs fresh consent. Article 13(2) of the same directive, the so-called soft opt-in, lets you send direct marketing for your own similar products or services to an existing customer whose address you obtained in the context of a sale, provided you gave them a clear, free way to refuse at the point of collection and repeat that offer in every message. Where it applies, the GDPR side is typically legitimate interests rather than consent (Recital 47 names direct marketing as a possible legitimate interest). But all of its conditions have to hold, and member states read them narrowly: a free signup is generally not a sale, Germany’s transposition applies the conditions strictly and cumulatively, and France’s CNIL interprets “similar products” tightly. If you plan to rely on it, record which national rules apply to your recipients and be certain the opt-out was genuinely offered at collection. For everyone else, opt-in remains the safe default: it is valid in every member state and requires no analysis of what counts as similar.</p>

<aside class="scenario"><div class="scenario-label">Scenario</div><p class="scenario-narrative">Maya’s team ships a project-management app. Growth is flat, so she emails the entire free-tier list: <em>“New Pro plan -- 20% off this week.”</em> It feels harmless: they’re already her users. But this isn’t a service email or an update about a feature they use; it’s a <em>promotion</em>, and promotional email needs prior opt-in consent under Article 6(1)(a) and the ePrivacy Directive. Her signup form never asked: “marketing” was folded into the “I accept the Terms” checkbox, which isn’t valid consent. One annoyed recipient replies, then complains to their national supervisory authority.</p><div class="scenario-outcome"><strong>What actually happens</strong> No automatic fine, but Maya now has to prove a lawful basis she doesn’t have, stop the campaign, and rebuild her consent flow after the fact. For a company her size the real exposure is less the headline statutory ceiling than the scramble, a possible corrective order, and the enterprise prospect whose security review pauses the moment it sees an open complaint.</div></aside>

<h2 id="the-dpa-with-hetzner">The DPA with Hetzner</h2>

<p><a href="https://gdpr-info.eu/art-28-gdpr/">Article 28</a> requires that when you engage a processor (which Hetzner is) you have a written contract covering specific requirements. This is called a Data Processing Agreement (DPA), or in German, an Auftragsverarbeitungsvertrag (AVV). You cannot legally use Hetzner to store or process personal data without one.</p>

<p>Hetzner provides their standard DPA through <a href="https://docs.hetzner.com/general/company-and-policy/data-protection-at-hetzner/">their customer portal</a>. You conclude it once, for Cloud and Robot alike, in the central account portal at <a href="https://accounts.hetzner.com/account/dpa">accounts.hetzner.com/account/dpa</a>; agreeing is a checkbox, with no signature required. Accept it. This is a minutes-long administrative task, not a negotiation; they have a standard agreement that meets Article 28 requirements.</p>

<p>The DPA covers Hetzner’s obligations: processing only on your instructions, confidentiality, security measures, sub-processor management, assistance with data subject requests, and deletion of data at termination. Their <a href="https://www.hetzner.com/AV/subcontractors.pdf">listed sub-processors</a> are documented in the agreement and on their website.</p>

<p>One thing the tier does not change: Cloud or <a href="https://robot.hetzner.com">Robot</a>, shared-vCPU or dedicated, the Article 28 obligation is identical and so is your legal exposure. What <em>does</em> differ between them is how Hetzner could technically reach your data – and that turns out to be an Article 32 question, not an Article 28 one. It’s covered under <a href="#security-measures-under-article-32">security measures</a> below.</p>

<h2 id="the-dpa-with-your-email-provider">The DPA with your email provider</h2>

<p>Every email you send goes through a third-party SMTP provider. That provider receives email addresses and sometimes message content. They are a processor under <a href="https://gdpr-info.eu/art-28-gdpr/">Article 28</a>, and you need a DPA with them too.</p>

<p><strong>Use an EU-incorporated provider.</strong> If your email provider is incorporated in the US, you face an international data transfer obligation under <a href="https://gdpr-info.eu/chapter-5/">GDPR Chapter V (Articles 44-50)</a>. This requires either an adequacy decision for the destination country, Standard Contractual Clauses, or Binding Corporate Rules. The US does not have a general adequacy decision; the <a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32023D1795">EU-US Data Privacy Framework</a> covers only US companies that have self-certified under the programme. This isn’t insurmountable, but it adds documentation overhead and carries ongoing legal risk given the track record of adequacy decisions being challenged.</p>

<p>EU-incorporated email providers eliminate this problem entirely. <a href="https://www.brevo.com/company/gdpr/">Brevo</a> (formerly Sendinblue) is incorporated in France and processes email on EU infrastructure. Mailpace is a reasonable alternative, with the caveat that it’s incorporated in the UK – not an EU member state, though the UK GDPR adequacy decision means transfers are currently permitted (worth monitoring). Both offer standard DPAs that you can accept through their dashboard. Check the corporate chain rather than the brand – and then check it again in a year. Mailjet still reads as French. It was bought by US-based Mailgun in 2019, and Mailgun was itself bought by Sweden’s Sinch in 2021. So the correct transfer analysis for Mailjet was one thing in 2018, a different thing in 2020, and a third thing today, and nobody emailed you on either occasion. This one happens to have landed back inside the EU. The next one might not, and you will find out by looking.</p>

<p>The DPA acceptance process with these providers is similar to Hetzner: find it in account settings, accept, done.</p>

<h2 id="privacy-notice-under-article-13">Privacy notice under Article 13</h2>

<p><a href="https://gdpr-info.eu/art-13-gdpr/">Article 13</a> requires that you provide specific information to data subjects at the time their data is collected. This means at account signup. The information you must provide:</p>

<ul>
  <li><strong>Identity and contact details of the controller</strong>: your company name and address, or your personal details if you’re operating as an individual.</li>
  <li><strong>Contact details of the DPO</strong>, if you have one. See below on whether you need one.</li>
  <li><strong>Purposes and legal basis</strong> for each processing activity. Not a vague “to provide our services”, but the specific purposes (account management, service delivery, product communications) and the specific basis (Article 6(1)(b) for service delivery, Article 6(1)(f) for product emails, Article 6(1)(a) for marketing if applicable).</li>
  <li><strong>Legitimate interests pursued</strong>, where that’s your basis. Brief description of the interest and the balancing assessment.</li>
  <li><strong>Recipients or categories of recipients</strong>: Hetzner, your email provider. You don’t need to list individual employees.</li>
  <li><strong>Transfers to third countries</strong>, if any. If you’re using only EU processors, state that explicitly.</li>
  <li><strong>Retention period</strong>, or the criteria used to determine it. “We retain your data for the duration of your account, plus 30 days after deletion to allow for recovery, and billing records for 7 years as required by applicable tax law” is the kind of specificity required.</li>
  <li><strong>Data subject rights</strong>: the right to access (<a href="https://gdpr-info.eu/art-15-gdpr/">Article 15</a>), rectification (<a href="https://gdpr-info.eu/art-16-gdpr/">Article 16</a>), erasure (<a href="https://gdpr-info.eu/art-17-gdpr/">Article 17</a>), restriction (<a href="https://gdpr-info.eu/art-18-gdpr/">Article 18</a>), data portability (<a href="https://gdpr-info.eu/art-20-gdpr/">Article 20</a>), and objection (<a href="https://gdpr-info.eu/art-21-gdpr/">Article 21</a>). Plus the right to withdraw consent where consent is the basis, and the right to lodge a complaint with a supervisory authority.</li>
</ul>

<p>This goes in your privacy policy, which must be linked at the point of data collection: the signup form, not buried in a footer that’s three clicks away from where the user enters their email.</p>

<h2 id="data-subject-rights-you-must-handle">Data subject rights you must handle</h2>

<p>Users have enforceable rights that you must be able to fulfill within one month of a request (<a href="https://gdpr-info.eu/art-12-gdpr/">Article 12</a>). The practical requirements:</p>

<p><strong>Access (<a href="https://gdpr-info.eu/art-15-gdpr/">Article 15</a>):</strong> A user can ask what data you hold about them. You must provide a copy. For a SaaS, this means being able to export everything associated with a user account: their profile data, their content, their email address, activity logs if you store them. If your schema makes this difficult to produce, that’s a technical debt that’s now a legal obligation.</p>

<p><strong>Erasure (<a href="https://gdpr-info.eu/art-17-gdpr/">Article 17</a>):</strong> A user can request deletion of their data. You must comply unless you have grounds for retention (legal obligation, public interest, establishment of legal claims). For a cancelled account, “we need to keep this for 30 days for recovery” is supportable. “We keep it indefinitely for analytics” is not. Build an account deletion process that actually deletes the data, and document what you retain and why.</p>

<p><strong>Portability (<a href="https://gdpr-info.eu/art-20-gdpr/">Article 20</a>):</strong> Where your processing is based on consent or contract and carried out by automated means, users can request their data in a structured, commonly used, machine-readable format. JSON or CSV export of their account data satisfies this. This only applies to data they provided to you, not derived data you generated about them.</p>

<p><strong>Objection (<a href="https://gdpr-info.eu/art-21-gdpr/">Article 21</a>):</strong> Where you’re relying on legitimate interests, users can object. You must stop processing unless you can demonstrate compelling legitimate grounds. Direct marketing is the exception to that exception: under Article 21(2) an objection to marketing is <strong>absolute</strong>. There is no balancing test and nothing to weigh – they object, you stop. For product emails, that means a working unsubscribe mechanism that actually stops the emails and is honored promptly.</p>

<p>Two more round out the set, and both are usually cheap in a SaaS. <strong>Rectification (<a href="https://gdpr-info.eu/art-16-gdpr/">Article 16</a>)</strong> is a user telling you their name is spelled wrong – an editable profile page satisfies most of it. <strong>Restriction (<a href="https://gdpr-info.eu/art-18-gdpr/">Article 18</a>)</strong> is the ability to freeze processing while something is contested, rather than deleting it: in practice, a flag that keeps the record but takes it out of use.</p>

<p>So: a way to receive these requests (an email address is fine), a documented process for handling them (a simple internal runbook is enough), and the technical capability to actually fulfill them.</p>

<aside class="scenario"><div class="scenario-label">Scenario</div><p class="scenario-narrative">Tomas gets a plain-text email: <em>“Please send me all the data you hold about me, and then delete my account.”</em> A simple request -- until he opens his database. One user’s data is spread across the app tables, Stripe metadata, support tickets, three months of application logs, and the analytics events he fires on every click. There’s no “export one user” button; nobody built one. The Article 12 clock gives him one month.</p><div class="scenario-outcome"><strong>What actually happens</strong> Access (Article 15) and erasure (Article 17) aren’t optional, and “our schema makes that hard” is no defence -- only technical debt that just became a legal deadline. The fix is unglamorous and has to exist <em>before</em> the request lands: one routine that gathers everything tied to a user id, and one that deletes or anonymises it. Build it once, and every future request is a button instead of a fire drill.</div></aside>

<h2 id="records-of-processing-activities">Records of processing activities</h2>

<p><a href="https://gdpr-info.eu/art-30-gdpr/">Article 30</a> requires maintaining a record of processing activities. There’s an exemption for organisations with fewer than 250 employees, but it doesn’t apply if the processing “is not occasional.” For a SaaS that continuously processes user data as part of its core function, the processing is not occasional. The exemption doesn’t apply to you.</p>

<p>The record doesn’t have to be elaborate. The <a href="https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/accountability-and-governance/accountability-framework/records-of-processing-and-lawful-basis/">ICO’s records of processing guidance</a> covers what a ROPA should contain. A document (a spreadsheet or an Outline page) with the following is sufficient:</p>

<ul>
  <li>Name and contact details of the controller</li>
  <li>Purposes of the processing</li>
  <li>Categories of data subjects (your users)</li>
  <li>Categories of personal data (email addresses, user-generated content, usage data)</li>
  <li>Categories of recipients (Hetzner, email provider)</li>
  <li>Where applicable, transfers to third countries (and the safeguards, if any)</li>
  <li>Envisaged time limits for erasure</li>
  <li>General description of technical and organisational security measures</li>
</ul>

<p>Two or three rows in a table (one for account/service data, one for email communications) is a complete ROPA for a simple SaaS. Its real value is as evidence that you’ve thought through your processing rather than stumbled into it.</p>

<p>Most of that list should look familiar, because it is mostly the same information as your Article 13 privacy notice: controller, purposes, recipients, transfers, retention. The two documents differ in who they are written for – your users, and a regulator who asks – rather than in what they are about. Gather the facts once and write them into both.</p>

<h2 id="security-measures-under-article-32">Security measures under Article 32</h2>

<p><a href="https://gdpr-info.eu/art-32-gdpr/">Article 32</a> requires “appropriate technical and organisational measures” to ensure a level of security appropriate to the risk. The regulation does not mandate specific measures, but specifies factors to consider: the state of the art, the costs, the nature of the data, and the risks. For a SaaS holding email addresses and user-generated content rather than special-category data like health records, that bar is not high: you are expected to take the obvious precautions competently, not to build a bank’s security programme.</p>

<p>Appropriate measures for your context:</p>

<ul>
  <li><strong>Encryption in transit</strong>: <span class="term-wrap"><span class="term" tabindex="0">TLS</span><span class="term-note" role="note"><span class="term-note-head">TLS</span><span class="term-note-body">The encryption behind the padlock in your browser - it scrambles data traveling between a visitor and your server so nobody in between can read it. (It’s the ‘S’ in HTTPS.)</span></span></span>
 for all HTTP connections (Caddy handles this automatically with automatic certificate renewal). Also TLS for connections between your application and your database.</li>
  <li><strong>Encryption at rest</strong>: no Hetzner tier encrypts your disk by default, and on every one of them Hetzner has a technical path to it. This is the measure worth your attention, and the reason is below.</li>
  <li><strong>Access control</strong>: Limit who can access production systems. Two-person team with shared root credentials is not appropriate. Use <span class="term-wrap"><span class="term" tabindex="0">SSH keys</span><span class="term-note" role="note"><span class="term-note-head">SSH keys</span><span class="term-note-body">A pair of cryptographic files that log you into a server in place of a password - far harder to guess or steal, and the standard way to secure remote server access.</span></span></span>
, not passwords. Administer the server through a non-root account with <code class="language-plaintext highlighter-rouge">sudo</code> and disable root SSH login (<code class="language-plaintext highlighter-rouge">PermitRootLogin no</code>): root is the account attackers try first, and a per-person sudo account gives you an audit trail that a shared root login can’t. Authentik or similar for SSO to internal tooling.</li>
  <li><strong>Backups</strong>: Automated, and – the part everyone skips – restored at least once, so you know the restore works. Article 32(1)(c) asks for the ability to <em>restore</em> personal data in a timely manner; it says nothing about your ability to take a backup. Then match the copy’s distance to the failure you’re insuring against. On the same server, it survives you dropping the wrong table but not a dead disk. In the same Hetzner account, it survives the dead disk but not an account that gets compromised, or suspended over a billing dispute. Only a copy under separate credentials – ideally at a second provider – survives that. And turn on object lock, so that an attacker who does get your keys can’t delete the backups along with everything else.</li>
  <li><strong>Logging</strong>: Retain application and infrastructure logs sufficient to reconstruct what happened after an incident.</li>
  <li><strong>Dependency management</strong>: Track your dependencies and apply security updates promptly. Running a version with a known critical <span class="term-wrap"><span class="term" tabindex="0">CVE</span><span class="term-note" role="note"><span class="term-note-head">CVE</span><span class="term-note-body">A publicly catalogued security flaw with an ID number (like CVE-2024-1234). ‘A known CVE’ means the weakness is public - so attackers may already be probing for it.</span></span></span>
 is a specific Article 32 failure you’d need to explain to a supervisory authority after a breach.</li>
</ul>

<p><strong>Why encryption at rest is the one to spend time on.</strong> Hetzner Cloud VMs run on shared KVM hypervisors that Hetzner operates. They can attach your volume, snapshot it, or boot it into rescue mode – and that is true on a dedicated-vCPU tier (CCX) exactly as much as on a shared one (CX/CPX/CAX). “Dedicated vCPU” only means your cores aren’t time-sliced with other tenants for performance consistency. It says nothing about isolation from the host operator, and reading it that way is the most common mistake on this page.</p>

<p>Bare metal doesn’t close the door either. <a href="https://robot.hetzner.com">Robot</a>, Hetzner’s actual dedicated-hardware product, has no shared hypervisor at all – which is confusingly the opposite of what “dedicated” suggests if you’ve only met Cloud’s CCX line. But Robot ships a rescue system Hetzner can boot the machine into from their own panel, and that reaches an unencrypted disk without anyone going near the hardware.</p>

<figure>
  <img src="/assets/images/diagrams/hetzner-tiers.svg" alt="A comparison of Hetzner Cloud and Robot. Cloud runs on a shared KVM hypervisor on every tier, so Hetzner can snapshot or attach your disk. Robot has no hypervisor, but it does have a rescue system Hetzner can boot the machine into, reaching an unencrypted disk without touching the hardware. Neither encrypts the disk by default, both require a DPA under Article 28, and your legal exposure is identical." />
  <figcaption>Two traps: "dedicated vCPU" buys performance, not isolation -- and bare metal still has a rescue system you don't control.</figcaption>
</figure>

<p>So the tier is not the lever. What gets you a defensible Article 32 position is disk encryption whose keys you hold, kept somewhere the disk itself doesn’t reveal, plus tight database access control and an audit trail. It is also, as the next section but one explains, the single measure that can excuse you from telling your users about a breach at all.</p>

<p>Document these measures. A half-page description in your ROPA or a separate security policy is enough for a small team. What you’re creating is evidence that you made deliberate choices, not proof that your security is perfect.</p>

<h2 id="breach-notification-under-article-33">Breach notification under Article 33</h2>

<p>If you experience a personal data breach – unauthorized access, accidental disclosure, loss of availability – you must notify your national supervisory authority within 72 hours of becoming aware of it under <a href="https://gdpr-info.eu/art-33-gdpr/">Article 33</a>, unless the breach is unlikely to result in a risk to the rights and freedoms of natural persons. The 72-hour clock starts when you know enough to assess that a breach has occurred, not when you know the full details.</p>

<p>The notification must include: the nature of the breach, the categories and approximate number of affected data subjects, the categories and approximate number of personal data records, the likely consequences, and the measures taken or proposed to address it. You can provide information in phases if the full picture isn’t available in 72 hours.</p>

<p>If the breach is likely to result in high risk to individuals – their data was exfiltrated and could be used for fraud or identity theft – you must also notify the affected users without undue delay under <a href="https://gdpr-info.eu/art-34-gdpr/">Article 34</a>.</p>

<p>Article 34(3) gives three ways out of <em>that</em> second notification, and the first is why disk encryption keeps coming up in this post. If the data was rendered unintelligible to whoever took it – encrypted, and they didn’t take the keys along with it – you generally don’t have to tell the individuals at all. The other two: you’ve since taken measures that mean the high risk is no longer likely to materialise, or telling everyone individually would take disproportionate effort, in which case you make a public communication instead.</p>

<p>Read that carefully, because it’s the part people get backwards. An Article 34(3) exemption spares you the call to your <em>users</em>. It does not spare you the call to the <em>authority</em> – the 72-hour clock under Article 33 runs either way, encrypted or not. And the authority can still order you to tell the individuals anyway under Article 34(4). Encryption buys you a great deal here. It does not buy you silence.</p>

<p>Which is also the practical argument for holding your own keys, and for keeping them somewhere the person who walked off with the disk could not reach. An encrypted volume whose key sits unencrypted on the same host has bought you nothing at all.</p>

<figure>
  <img src="/assets/images/diagrams/breach-72h.svg" alt="A flow. You become aware of a breach. Notifying the supervisory authority within 72 hours under Article 33 is the default; the only way out is if a risk to rights and freedoms is unlikely, and you must be able to show it. If there is a high risk to individuals you must also notify them under Article 34, unless one of the three Article 34(3) exemptions applies: the data was unintelligible (encrypted, keys not taken), the risk is no longer likely, or individual notice would take disproportionate effort. An exemption spares you the call to the individuals but never the call to the authority. Either way, Article 33(5) requires you to document the breach." />
  <figcaption>Encryption can excuse you from telling your users. It never excuses you from telling the regulator.</figcaption>
</figure>

<p>Know which supervisory authority covers you before a breach happens: competence follows where your company is established, not where your servers sit. If you’re incorporated in one EU member state, that’s your lead supervisory authority under the one-stop-shop mechanism. A full list of national authorities is on the <a href="https://edpb.europa.eu/about-edpb/about-edpb/members_en">EDPB members page</a>. In Germany, the competent authority for a private company is the data protection authority of the Land where it’s established (for example the <a href="https://www.lda.bayern.de/en/index.html">BayLDA</a> for Bavarian companies), not the federal BfDI. For France, it’s the <a href="https://www.cnil.fr/en/home">CNIL</a>. For Ireland, the <a href="https://www.dataprotection.ie/">DPC</a>.</p>

<aside class="scenario"><div class="scenario-label">Scenario</div><p class="scenario-narrative">A contractor pushes a debug build on Friday that logs full request bodies -- including password-reset tokens and email addresses -- to a third-party log viewer. Nobody notices until Tuesday. Priya realizes it’s a personal-data breach, then reads Article 33: the 72-hour clock started when she <em>became aware</em>, not when she has the full picture. She doesn’t know which supervisory authority to notify, has never drafted a notification, and can’t yet say how many users are affected.</p><div class="scenario-outcome"><strong>What actually happens</strong> The 72 hours are for notifying, not for finishing the investigation: you’re allowed to report in phases. What sinks teams here isn’t the breach itself; it’s burning the first day of the clock working out who to call and what to say. Knowing your lead supervisory authority in advance and keeping a one-page notification template turns a panicked weekend into a form you fill out.</div></aside>

<h2 id="do-you-need-a-data-protection-officer">Do you need a Data Protection Officer?</h2>

<p><a href="https://gdpr-info.eu/art-37-gdpr/">Article 37</a> requires a DPO in three situations: you’re a public authority, your core activities require large-scale, regular, and systematic monitoring of individuals, or your core activities consist of large-scale processing of special categories of data (health, biometrics, political opinions, etc.).</p>

<p>A SaaS that stores email addresses and user-generated content and sends product emails does not trigger any of these. Many small EU SaaS companies appoint one voluntarily or because a consultant suggested it; it’s not required and not worth the overhead at an early stage.</p>

<h2 id="does-nis2-apply">Does NIS2 apply?</h2>

<p>The <a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32022L2555">NIS2 Directive (Directive 2022/2555)</a>, transposed into national law by October 2024, applies to “essential entities” and “important entities” in specified sectors. The size threshold for most “important entity” categories is medium enterprises: at least 50 employees, or over €10 million in both annual turnover and balance-sheet total.</p>

<p>If you’re below both thresholds, NIS2 almost certainly does not apply to you as a direct regulatory obligation. The notable exception is companies in certain sectors regardless of size (DNS providers, TLD registries, trust service providers, specific critical infrastructure), which are probably not you.</p>

<p>The indirect implication of NIS2 is more likely to be relevant: if your customers are NIS2 entities, they will flow down supply chain security requirements to their ICT providers. Your enterprise customers may ask for evidence of security measures even if you’re not directly in scope. The security documentation from Article 32 compliance covers most of what they’ll ask for.</p>

<h2 id="what-you-dont-need">What you don’t need</h2>

<p>To be explicit about what this situation does not require:</p>

<ul>
  <li><strong>Cookie consent banners</strong> for cookies that are strictly necessary for the service to function (session cookies, authentication tokens). The <a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32002L0058">ePrivacy Directive</a> requires consent for non-essential cookies: analytics, advertising, tracking. If you’re not running analytics or ad tracking, you don’t need a cookie banner, whatever a consent plugin’s default settings suggest.</li>
  <li><strong>An EU representative under <a href="https://gdpr-info.eu/art-27-gdpr/">Article 27</a></strong>. That requirement applies to controllers established outside the EU.</li>
  <li><strong>ISO 27001 certification</strong> to be compliant. Article 32 requires appropriate measures, not certification. Certification is a way of demonstrating those measures to enterprise customers, not a legal prerequisite.</li>
</ul>

<h2 id="the-actual-checklist">The actual checklist</h2>

<p>Everything above condenses to this:</p>

<ol>
  <li>Sign <a href="https://docs.hetzner.com/general/company-and-policy/data-protection-at-hetzner/">Hetzner’s DPA</a> through your account portal.</li>
  <li>Choose an EU-incorporated email provider (e.g. <a href="https://www.brevo.com/company/gdpr/">Brevo</a>) and accept their DPA.</li>
  <li>Document your lawful basis for each processing activity (<a href="https://gdpr-info.eu/art-6-gdpr/">Article 6</a>): account management = Art 6(1)(b); product emails = Art 6(1)(f) with a brief LIA; marketing = Art 6(1)(a) with opt-in.</li>
  <li>Write a privacy notice containing all <a href="https://gdpr-info.eu/art-13-gdpr/">Article 13</a> information; link it at signup.</li>
  <li>Create a ROPA (<a href="https://gdpr-info.eu/art-30-gdpr/">Article 30</a>): a simple document listing your processing activities, data categories, recipients, and retention periods.</li>
  <li>Document your security measures (<a href="https://gdpr-info.eu/art-32-gdpr/">Article 32</a>): encryption in transit, <strong>encryption at rest with a key you hold and Hetzner doesn’t</strong>, access controls, <strong>a backup you have actually restored at least once</strong>, update policy.</li>
  <li>Set up a way to receive and fulfill data subject requests: access (<a href="https://gdpr-info.eu/art-15-gdpr/">Art 15</a>), erasure (<a href="https://gdpr-info.eu/art-17-gdpr/">Art 17</a>), portability (<a href="https://gdpr-info.eu/art-20-gdpr/">Art 20</a>), and objection (<a href="https://gdpr-info.eu/art-21-gdpr/">Art 21</a>) – which for most SaaS means an unsubscribe link that genuinely stops the emails.</li>
  <li>Know your supervisory authority (<a href="https://edpb.europa.eu/about-edpb/about-edpb/members_en">EDPB members list</a>) and their breach notification portal before you need it (<a href="https://gdpr-info.eu/art-33-gdpr/">Art 33</a>).</li>
</ol>

<p>The paperwork really is small. Two DPAs, a lawful-basis note, a privacy notice, and a ROPA that fits in a spreadsheet – a week or two of admin, and anyone quoting you a six-month programme for it should be asked what the other five months are for.</p>

<p>The capability underneath the paperwork is not paperwork. Article 12 gives you one month to answer a request, which only helps if something can actually gather one user’s data out of your app tables, your logs, your billing provider and your support inbox, delete it when they ask, and leave a record that it did. Article 33 gives you 72 hours, which only helps if you find out at all. Those are engineering problems, and writing a document about them does not solve them. They also get harder every time you add a processor, an analytics tool, or a feature that touches personal data – which is to say, they get harder as the company succeeds.</p>

<p>And this is the floor for one specific situation: an EU-established SaaS holding email addresses and user content on EU infrastructure. Add health data, children’s data, employee records, automated decision-making, or a processor outside the EU, and the analysis changes. Nothing above is the whole of the GDPR. It is the part that applies to you today.</p>

<p>The documents take a fortnight. Keeping them true is the job.</p>

<p><em>Edited 2026-07-24.</em> Two small corrections after a fact-check: GDPR Chapter V spans Articles 44 to 50, not 44 to 49, and Hetzner’s DPA is now concluded once in the central account portal at accounts.hetzner.com rather than separately in the Cloud and Robot interfaces. The marketing email section also gained a paragraph on the ePrivacy Article 13(2) soft opt-in for existing customers, which the original text passed over in favor of the blanket opt-in rule.</p>

<p><em>Edited 2026-07-27.</em> Corrected the NIS2 size threshold: qualifying as a medium enterprise means at least 50 employees, or exceeding €10 million in both annual turnover and balance-sheet total – not €10 million in turnover alone.</p>]]></content><author><name>Ryan</name><email>ryan@fortibus-consulting.com</email></author><category term="compliance" /><category term="gdpr" /><category term="gdpr" /><category term="nis2" /><category term="hetzner" /><category term="dpa" /><category term="privacy" /><category term="email" /><category term="eu-cloud" /><category term="saas" /><summary type="html"><![CDATA[A walkthrough of the GDPR and ePrivacy obligations that apply when you run an EU SaaS on Hetzner, store user email addresses, and send product emails - with the specific articles and the specific steps.]]></summary></entry><entry><title type="html">The European Cloud Gap: Why EU Startups Still Can’t Match US Infrastructure</title><link href="https://fortibus-consulting.com/insights/2026/07/the-european-cloud-gap/" rel="alternate" type="text/html" title="The European Cloud Gap: Why EU Startups Still Can’t Match US Infrastructure" /><published>2026-07-03T00:00:00+02:00</published><updated>2026-07-03T00:00:00+02:00</updated><id>https://fortibus-consulting.com/insights/2026/07/the-european-cloud-gap</id><content type="html" xml:base="https://fortibus-consulting.com/insights/2026/07/the-european-cloud-gap/"><![CDATA[<p>Every EU founder runs into the friction eventually, usually around the time they’re choosing between GitHub and “something else”. Your US counterpart spun up Vercel, GitHub, PagerDuty, Vanta, and Notion in an afternoon. You’re reading Article 28 of the GDPR and wondering whether your CI provider’s <span class="term-wrap"><span class="term" tabindex="0">DPA</span><span class="term-note" role="note"><span class="term-note-head">DPA</span><span class="term-note-body">Data-processing agreement - the contract that spells out how an outside vendor is allowed to handle personal data on your behalf. GDPR requires one with every such vendor.</span></span></span>
 actually covers what you think it covers. And the gap widens with every compliance framework your sector falls under.</p>

<h2 id="europe-has-the-tools-not-the-integration">Europe has the tools, not the integration</h2>

<p>What’s missing is not raw capability. Europe has credible alternatives in almost every infrastructure category. Gitea and Forgejo compete with GitHub. Authentik and Keycloak handle identity. Grafana and Prometheus are the de facto standard open-source monitoring stack – and while Grafana Labs is a US company, the software is open source and fully self-hosted, with no network dependency on any US-controlled service. CISO Assistant, built by a French company, handles <span class="term-wrap"><span class="term" tabindex="0">GRC</span><span class="term-note" role="note"><span class="term-note-head">GRC</span><span class="term-note-body">Governance, risk &amp; compliance - software for tracking the security rules you have to follow and keeping the evidence that proves you follow them.</span></span></span>
 across ISO 27001, NIS2, DORA, and GDPR simultaneously.</p>

<p>The gap shows up when you try to assemble them into a stack. Microsoft and Amazon are not really selling you tools. They are selling you the <em>integration</em> – and it is very good.</p>

<div class="tabs" role="group" aria-label="Compare the same platform on Azure or on AWS">
  <input type="radio" name="cloud" id="tab-azure" checked="" />
  <input type="radio" name="cloud" id="tab-aws" />
  <div class="tab-labels">
    <label for="tab-azure">Azure</label>
    <label for="tab-aws">AWS</label>
  </div>
  <div class="tab-panel tab-panel-azure">
    <figure>
      <img src="/assets/images/diagrams/platform-azure.svg" alt="Eight capabilities, side by side. Azure: App Service or Container Apps, Front Door and WAF, Entra ID with Easy Auth, Azure DevOps Pipelines, Key Vault with managed identity, Application Insights and Monitor, Defender for Cloud, and Purview with Microsoft's own attestations. Self-hosted in the EU: a Hetzner VM with Docker Compose, Caddy, Authentik, Gitea and Woodpecker, Vaultwarden, Prometheus with Grafana and Loki, Trivy, and CISO Assistant where the evidence is yours to produce." />
      <figcaption>Azure really does sell you the integration. It comes with a jurisdiction attached.</figcaption>
    </figure>
  </div>
  <div class="tab-panel tab-panel-aws">
    <figure>
      <img src="/assets/images/diagrams/platform-aws.svg" alt="Eight capabilities, side by side. AWS: App Runner or ECS Fargate, an Application Load Balancer with ACM and WAF, Cognito or IAM Identity Center, CodePipeline and CodeBuild, Secrets Manager, CloudWatch and X-Ray, Inspector and Security Hub, and Audit Manager with Amazon's own attestations. Self-hosted in the EU: a Hetzner VM with Docker Compose, Caddy, Authentik, Gitea and Woodpecker, Vaultwarden, Prometheus with Grafana and Loki, Trivy, and CISO Assistant where the evidence is yours to produce." />
      <figcaption>AWS asks more of you than Azure does. The jurisdiction comes attached either way.</figcaption>
    </figure>
  </div>
</div>

<p>It’s worth being honest about what that buys, because the sales pitch happens to be true. On Azure, a .NET service goes to App Service straight from a <span class="term-wrap"><span class="term" tabindex="0">CI/CD</span><span class="term-note" role="note"><span class="term-note-head">CI/CD</span><span class="term-note-body">Continuous integration / delivery - automation that tests your code and ships it to your servers every time you make a change, instead of doing it by hand.</span></span></span>
 pipeline; you point Easy Auth at Entra ID and the app has <span class="term-wrap"><span class="term" tabindex="0">SSO</span><span class="term-note" role="note"><span class="term-note-head">SSO</span><span class="term-note-body">Single sign-on - one login that gets a person into every tool, instead of a separate password for each app.</span></span></span>
 in about three clicks, with no library to add and no redirect URIs to get wrong; managed identity lets it read from Key Vault without a secret ever landing in a config file. AWS asks for more – a VPC with its subnets and route tables, IAM roles and policies, a load balancer with target groups and listeners – but it is exceptionally well-trodden ground, and there is a written-up answer for every step of it.</p>

<p>Self-hosting is where the wiring bill arrives. Gitea doesn’t know about Woodpecker. Woodpecker doesn’t know about your <span class="term-wrap"><span class="term" tabindex="0">OIDC provider</span><span class="term-note" role="note"><span class="term-note-head">OIDC provider</span><span class="term-note-body">The one login service that all your other apps trust to answer ‘who is this user?’ - the hub that makes single sign-on work. (OIDC is the standard the apps use to ask.)</span></span></span>
. Nothing knows which routes are supposed to sit behind a login and which have to stay open, or whether last night’s backup ran. Every line between those components is yours to draw, and then yours to keep working. Each tool is good on its own; the integration burden falls entirely on you.</p>

<p>And there’s a part that never appears on a pricing page. Both hyperscalers hand you their ISO 27001, SOC 2, and C5 attestations for everything underneath your application. That is a real lift, it is the strongest card they hold, and you should take it seriously before walking away from it.</p>

<p>But an attestation is a statement about controls, and jurisdiction isn’t a control – it’s a fact about who operates the service and which courts can compel them. So the inheritance runs both ways, and only one direction is on the sales page. Their certifications transfer to you. So does their jurisdiction.</p>

<p>Early-stage startups should be spending their engineering time on product, not on wiring identity providers to <span class="term-wrap"><span class="term" tabindex="0">reverse proxies</span><span class="term-note" role="note"><span class="term-note-head">reverse proxies</span><span class="term-note-body">A reverse proxy is a gatekeeper server that sits in front of your apps: every web request hits it first, and it forwards each one to the right app - handling HTTPS and login checks in one place.</span></span></span>
 and then debugging forward-auth headers at midnight. That is exactly the bind: the vendors who will gladly do that wiring for you are the ones whose jurisdiction you were trying to leave.</p>

<h2 id="then-compliance-stacks-on-top">Then compliance stacks on top</h2>

<p>The integration gap is annoying on its own. Add EU compliance and it starts costing real money.</p>

<p>GDPR has been around long enough that most founders understand the basics: lawful basis, DPA with processors, 72-hour breach notification to your supervisory authority. But NIS2, which member states had to transpose into national law by October 2024, added a whole second rulebook. If your startup provides services in sectors like digital infrastructure, ICT service management, or cloud computing, you now face mandatory risk management measures under Article 21 that cover supply chain security, cryptographic controls, access management, incident handling, and business continuity. And Article 20 makes management personally liable for ensuring these measures are in place.</p>

<p>DORA adds another layer for anyone touching financial services. It demands ICT risk management frameworks, detailed incident classification and reporting timelines (initial notification within 4 hours of classifying an incident as major), and explicit contractual requirements with your ICT service providers.</p>

<p>Any one of these frameworks is manageable. It’s stacking them that hurts. A SaaS company incorporated in the EU is under GDPR from its first user, under NIS2 the moment it lands in scope, and under DORA’s flow-down requirements as soon as it sells to a bank: overlapping but non-identical sets of controls, each with its own audit trail and its own paperwork. And none of it <em>replaces</em> the SOC 2 report an enterprise buyer will ask for anyway.</p>

<p>A US startup building the same product starts with SOC 2, and picks up HIPAA only if it touches health data: one dominant framework with mature tooling (Vanta, Drata) and an ecosystem of auditors who know exactly what to check.</p>

<figure>
  <img src="/assets/images/diagrams/compliance-stack.svg" alt="The same SaaS product in two jurisdictions. Incorporated in the US: SOC 2, which is what buyers ask for, plus HIPAA only if it touches health data. Incorporated in the EU: that same SOC 2, still demanded by enterprise buyers, plus GDPR from day one, NIS2 once in scope, and DORA the moment it sells to a bank." />
  <figcaption>The EU company doesn't trade one rulebook for another. It carries the US one and the statutory ones together.</figcaption>
</figure>

<p>A fintech has it worse still: add its national supervisor’s requirements – DNB, for a Dutch fintech – to that pile, and every one of those regimes wants its own evidence.</p>

<h2 id="what-sovereign-actually-means-in-practice">What “sovereign” actually means in practice</h2>

<p>The CLOUD Act discussion is real, but it tends to stay abstract. The concrete version:</p>

<p>When your company stores operational data – source code, CI/CD pipelines, infrastructure credentials, incident logs, employee information – in a US-incorporated service, that data is subject to US government access requests regardless of where the servers physically sit. The provider can be compelled to produce it without notifying you. For regulated entities under NIS2 or DORA, auditors are starting to flag this as a compliance gap.</p>

<p>Sovereignty means more than “hosted in Europe”: the entire chain – the legal entity operating the service, the code, the infrastructure – has to sit outside the jurisdiction of foreign data access laws. Hetzner in Germany or Finland, OVHcloud in France, and self-hosted open-source software with no network dependency on a US-controlled service – that’s the combination that actually satisfies the requirement. For most tools that also means no US parent entity; where one exists – as with Grafana Labs, Authentik, or Keycloak – the test is that you run the software yourself, so there is no operator a foreign court order can compel.</p>

<h2 id="the-missing-middle">The missing middle</h2>

<p>The market has two extremes and an empty middle. On one end, you can buy managed EU cloud services. Scaleway, Hetzner Cloud, OVHcloud all offer VMs and object storage, and Scaleway and OVHcloud add managed databases. Those are building blocks, though. Nobody is offering “here’s your complete internal operations platform, with the compliance scaffolding included” – managed or otherwise.</p>

<p>On the other end, large enterprises hire infrastructure teams to build custom stacks. They can afford to spend six months integrating identity providers, setting up monitoring, configuring backup pipelines, and documenting everything for their ISO 27001 audit. A ten-person startup cannot.</p>

<figure>
  <img src="/assets/images/diagrams/missing-middle.svg" alt="Three boxes on a spectrum. On the left, managed EU building blocks from Scaleway, Hetzner and OVHcloud, which you still assemble yourself. On the right, custom enterprise stacks needing an infrastructure team and six months. The middle box, drawn as an empty dashed outline, is a pre-integrated sovereign-by-default platform: nobody sells it." />
  <figcaption>Both ends of this market are well served. The startup sits in the gap.</figcaption>
</figure>

<p>The middle would be a pre-integrated, sovereign-by-default stack that a technical founder can deploy in an afternoon, with the compliance scaffolding already in place.</p>

<p>An EU company could sell exactly that as a managed service, and it would answer the jurisdiction question perfectly well. Nothing here says otherwise; that is a real and legitimate product. But it adds a company to your supply chain, and not an equivalent one. A hosting provider holds a disk, and you can encrypt that disk with a key they don’t have – do that, and their access buys them nothing. Whoever <em>operates</em> your application holds the keys and the database in the clear, because an application cannot run on data it cannot read. That is the processor you have no technical defence against, and the only way to have none of them is to run the thing yourself.</p>

<p>Which means somebody has to do the integration work once, properly, and hand it over – instead of leaving every team to reinvent it.</p>

<h2 id="why-it-matters-now">Why it matters now</h2>

<p>Two regulatory timelines make this urgent.</p>

<p>NIS2 transposition deadlines have passed in most member states, and enforcement is ramping up. If your startup falls within the directive’s scope (and the scope is broader than most founders realize – “digital infrastructure” and “ICT service management” catch a lot of SaaS companies), you need documented, auditable security measures in place now.</p>

<p>DORA became applicable in January 2025. Financial institutions are already flowing down its requirements to their technology providers. If your startup sells to banks, insurers, or payment processors, your customers will start asking for evidence of ICT risk management frameworks and incident response capabilities in their procurement process.</p>

<p>Founders who sort this out before their first enterprise sales call will have a much easier time than the ones retrofitting it under procurement pressure. The retrofit gets more expensive with every customer and every new regulation.</p>

<p>Europe needs better defaults.</p>

<p><em>Edited 2026-07-24.</em> Corrected the provider comparison in the missing-middle section: Hetzner Cloud offers VMs and object storage but no managed database product; that offering belongs to Scaleway and OVHcloud.</p>

<p><em>Edited 2026-07-27.</em> Corrected the sovereignty section: Grafana Labs is not the lone US-parented exception – Authentik and Keycloak carry US parentage too, and the run-it-yourself test applies to all of them. Also clarified that DNB is the supervisor for a Dutch fintech specifically.</p>]]></content><author><name>Ryan</name><email>ryan@fortibus-consulting.com</email></author><category term="sovereignty" /><category term="compliance" /><category term="opinion" /><category term="eu-cloud" /><category term="gdpr" /><category term="nis2" /><category term="dora" /><category term="cloud-act" /><category term="startups" /><summary type="html"><![CDATA[EU startups have credible tools in every category and no turnkey stack that assembles them. What's actually missing, and why it costs more every year.]]></summary></entry></feed>