Skip to main content
Microsoft
separator
https://catalogartifact.azureedge.net/publicartifacts/lynxroute.zitadel-98e0e937-478a-463a-a8db-b5a24350ba17/image2_Azureready.png

Zitadel - Hardened Identity and Access Management

by Lynxroute

Zitadel 4.19.4 - CIS Level 1 hardened identity provider on Ubuntu 24.04 LTS, SBOM + CIS

What is Zitadel

Zitadel is an open-source identity and access management platform. It issues and validates identities for your own applications over the standards they already speak: OpenID Connect 1.0, OAuth 2.0 (including device and token-exchange flows), SAML 2.0 and SCIM 2.0. Users authenticate with passwords, passkeys/WebAuthn or one-time codes, and can be split across multiple organizations in one instance for multi-tenant products. Zitadel is event-sourced: every change is appended to an immutable log, so the audit trail is the storage model rather than a feature on top. Administration happens in a web Console, and everything it does is also on the API.

Why self-host Zitadel

Identity is the one system that sees every login, every session and every user attribute you hold. Self-hosting keeps that data in your own subscription and region, which turns GDPR residency and retention into a configuration choice, and cost scales with the VM rather than per monthly active user.

What this VM image adds

Security hardening:

  • Unique admin credential per instance - the administrator password, both database passwords and the encryption master key are generated on first boot into /root/zitadel-credentials.txt (0600). Nothing is baked into the image
  • Self-registration disabled - anonymous visitors cannot create accounts; enable it in the Console when you want public sign-up
  • TLS perimeter - nginx terminates HTTPS on 443 with a per-instance certificate generated at first boot; Certbot is pre-installed for a CA-signed one
  • Bundled PostgreSQL 17 on loopback only - the event store is unreachable from the network, uses scram-sha-256 and has no trust rule
  • Consent screens cannot be framed - X-Frame-Options DENY
  • Telemetry off - no usage reporting leaves the instance
  • CVE scan - every image is scanned with Trivy before release
  • UFW firewall - the API, the login service and PostgreSQL are blocked externally; only 22, 80 and 443 open
  • fail2ban - SSH brute-force protection
  • AppArmor - mandatory access control

OS hardening (CIS Level 1):

  • CIS Level 1 hardened - CIS Ubuntu 24.04 LTS Level 1 Benchmark via ansible-lockdown
  • auditd - system call auditing for critical paths
  • SSH hardening - PasswordAuthentication disabled, key-only access
  • Kernel hardening - SYN cookies, ASLR, rp_filter, TCP BBR
  • Azure IMDS egress - pre-configured (169.254.169.254, 168.63.129.16)

Compliance artifacts (inside the VM):

  • SBOM - CycloneDX 1.6 at /etc/lynxroute/sbom.json
  • CIS Conformance Report - OpenSCAP HTML at /etc/lynxroute/cis-report.html
  • Tailored CIS profile - /usr/share/doc/lynxroute/CIS_TAILORED_PROFILE.md
  • Licence and source offer - /usr/share/doc/lynxroute/LICENSES.txt carries the AGPL-3.0 text and the exact upstream revision built from

Quick Start

  1. Deploy the VM (Standard_D2s_v3 or larger recommended)
  2. SSH: ssh -i key.pem <username>@<PUBLIC_IP> (username set during VM creation, default: azureuser)
  3. Read the generated credentials: sudo cat /root/zitadel-credentials.txt
  4. Open https://<PUBLIC_IP>/ui/console, sign in, change the password and add a second factor
  5. Point your application at https://<PUBLIC_IP>/.well-known/openid-configuration

Creating your first users

This image ships one administrator and no mail provider, so plan the first accounts before inviting anyone.

  1. Self-registration is disabled by default. Enable it under Console -> Settings -> Login Behaviour -> "Register allowed" if you want public sign-up.
  2. No mail provider is configured, so invitation and password-reset mails cannot be sent yet. Create each user under Console -> Users -> New with an initial password you set, leave "Email verified" on, and pass it on out of band.
  3. For real invitation mails, configure SMTP under Console -> Settings -> Notification providers first.
  4. To move onto your own hostname, run sudo zitadel-set-domain idp.example.com so the OIDC issuer follows. Do this before registering applications.

Restrict port 443 to the networks that need it until the instance is fully configured.

English (United States)
Your Privacy Choices Opt-Out Icon Your Privacy Choices
Consumer Health Privacy Sitemap Contact Us Privacy & Cookies Terms of Use About our ads Manage cookies