Serialize enable with zone row FOR UPDATE, load public key fields only for status/DS, skip corrupt public material without raising, and tighten key-tag and API private-key leak tests. |
||
|---|---|---|
| .forgejo | ||
| .github | ||
| apps | ||
| clients | ||
| config | ||
| deploy | ||
| docs | ||
| env | ||
| external | ||
| priv/repo | ||
| release_builder | ||
| scripts | ||
| .credo.exs | ||
| .dockerignore | ||
| .env.example | ||
| .formatter.exs | ||
| .gitignore | ||
| AGENTS.md | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| elixir_buildpack.config | ||
| LICENSE | ||
| mise.toml | ||
| mix.exs | ||
| mix.lock | ||
| phoenix_static_buildpack.config | ||
| README.md | ||
| SECURITY.md | ||
Elektrine
Elektrine is an Elixir umbrella app. Shared runtime and persistence live in
apps/elektrine, the Phoenix host app lives in apps/elektrine_web, and the
product areas are split into their own umbrella apps.
Layout
apps/: umbrella appsclients/: client-side artifacts that are not shipped with the server releaseconfig/: shared compile-time and runtime configdeploy/: Docker, Caddy, onion, and VPN deploy assetsdocs/: architecture, protocol, API, and self-hosting docsenv/: example environment filesrelease_builder/: module-aware release build projectscripts/: release, deploy, and ops helpers
Main apps
apps/elektrine: shared domain logic,Repo, supervisors, accounts, uploads, notifications, calendar, module selection, frontend assets, and the cross-app UI components inlib/elektrine/componentsapps/elektrine_web: endpoint, router, plugs, layouts, theElektrineWeb.Components.UIdesign-system kit, and the account/admin shellapps/arblarg: chat facade plus LiveViews, JSON APIs, and PAT APIsapps/elektrine_social: timeline, communities, federation, social controllers, and LiveViewsapps/elektrine_email: mailbox, contacts, mail protocols, JMAP, WKD, and mail web routesapps/elektrine_vpn: WireGuard management and VPN UI/APIapps/elektrine_nerve: Nerve domain and extracted routesapps/elektrine_dns: managed DNS runtime, DNS API routes, and DNS LiveViewsapps/elektrine_uptime: uptime monitors, check history, incidents, and dashboard routesapps/atomine: proofs, personhood, account trust, and credit policy domain logicapps/kairo: capture, indexing, and graph-oriented knowledge featuresapps/paige: search provider integration and ranking support
Requests enter through ElektrineWeb.Router, pass through shared plugs and
module guards, and then land in the controller or LiveView mounted for the
selected feature set. Persistence stays centralized in Elektrine.Repo.
Identity Provider
Elektrine exposes an OpenID Connect-compatible identity provider on top of the existing OAuth tables:
- discovery:
/.well-known/openid-configuration - browser consent:
/oauth/authorize - public keys:
/oauth/jwks - token exchange:
/oauth/token - user info:
/oauth/userinfo - app management UI:
/account/developer/oidc/clients - grant review UI:
/account/developer/oidc/grants - dynamic registration:
POST /oauth/registerwhile signed in
Register OAuth apps with openid, profile, and email scopes to use this
flow. The current implementation supports the authorization code flow and
issues RS256 id_tokens for confidential clients.
Module Selection
Normal deployments use one public module switch:
ELEKTRINE_ENABLED_MODULEScontrols which product modules are turned on- release builds default to that same module list
ELEKTRINE_RELEASE_MODULESstill exists as an advanced override when you need to compile more modules than you expose at runtime
Supported module ids are chat, social, email, nerve, vpn, dns,
uptime, atomine, and kairo. proofs and personhood are accepted aliases
for atomine in the deploy scripts.
In normal use, set ELEKTRINE_ENABLED_MODULES and leave
ELEKTRINE_RELEASE_MODULES unset.
Local Development
From the repo root:
mix setup
Start the web app:
cd apps/elektrine
mix phx.server
Useful commands:
mix compile
mix check
mix test
mix test apps/elektrine/test
mix test apps/elektrine_web/test
mix test apps/elektrine_email/test
mix test apps/elektrine_social/test
mix test apps/elektrine_vpn/test
mix test apps/elektrine_nerve/test
mix test apps/elektrine_dns/test
Frontend assets live under apps/elektrine/assets.
Build And Deploy
The supported path for hosted or subset installs is the release builder:
scripts/release/deploy_release.sh --modules email,vpn
This builds assets, selects the requested feature apps, and writes the release
to _deploy_release/. deploy/docker/Dockerfile uses the same path.
For Docker deployments, use the wrapper instead of invoking docker compose
against deploy/docker/compose.full.yml directly:
scripts/deploy/docker_deploy.sh
The wrapper renders a module-aware Compose file first, sets
ELEKTRINE_ENABLED_MODULES, derives release modules from it by default, sets
mail runtime flags, and removes POP3, IMAP, and SMTP port bindings when
email is not selected. With no module or profile arguments, it deploys all
standard modules and Docker profiles; pass --modules or --profile only for a
smaller stack.
When vpn is selected, the Docker deploy also enables the bundled vpn
service automatically. That service runs the Docker-managed WireGuard node,
creates or restores its private key, derives the public key, and reconciles
peer state in-app.
Self-hosting
The self-hosting docs are split by profile:
core: Phoenix app and Postgres onlymail: Elektrine mail protocols; production SMTP edge/delivery still needs a separate Haraka deploymentdns: optional authoritative DNS service enabled through the Dockerdnsprofilevpn: optional Docker-managed WireGuard on the same stack, with optional fleet modeaddons: Caddy edge, TURN, Bluesky PDS, onion hosting, and client artifacts
Start with:
docs/api/external-api.mddocs/self-hosting/README.mddocs/self-hosting/docker.mddocs/self-hosting/core.mddocs/self-hosting/caddy.mddocs/self-hosting/mail.mddocs/architecture/dns-module.mddocs/self-hosting/turn.mddocs/self-hosting/vpn.mddocs/addons/onion.mddocs/clients/nerve-extension.mddocs/clients/static-site-github-deploys.md
Email Deployment
The email module in this repo is the mailbox/product side of the mail stack.
Production internet mail also needs
elektrine/elektrine-haraka,
which owns the SMTP edge and delivery pipeline.
This repo owns the mailbox product: UI, aliases, contacts, JMAP, WKD, message
storage, optional IMAP/POP3/SMTP submission listeners, and the Phoenix endpoints
that receive mail webhooks. elektrine-haraka owns inbound SMTP on port 25,
outbound delivery, Redis-backed queueing, and the worker that posts cleaned
inbound message data back into Phoenix.
If you enable the email module for production, run elektrine-haraka
alongside Elektrine and configure HARAKA_BASE_URL, an outbound Haraka API key,
and an inbound webhook key. Both stacks live on the same host as separate Docker
projects (/opt/elektrine and /opt/elektrine-haraka).
Deploy split
elektrine-harakaCI builds and pushesgit.elektrine.com/elektrine/elektrine-haraka(no SSH deploy).- Elektrine deploy rolls the app stack, then pulls that image and restarts the
Haraka compose services (
maybe_roll_haraka_stack), and applies wildcard TLS viaconfigure_haraka_wildcard_tls.sh.
Optional env for the roll: HARAKA_IMAGE, HARAKA_IMAGE_TAG (default latest),
HARAKA_DEPLOY_DIR, HARAKA_ROLL_ON_DEPLOY=false to skip.
Bluesky Integration
Bluesky support is part of the social stack.
- Outbound sync mirrors local public posts to Bluesky and keeps linked post state in sync for create, edit, delete, like, repost, and follow events. These jobs run through Oban, so failed outbound calls do not block the local action.
- Inbound sync, when
BLUESKY_INBOUND_ENABLED=true, polls notifications for connected accounts and turns replies, mentions, quotes, likes, and reposts on mirrored posts into local notifications. It can also store timeline items locally. - Managed mode, when
BLUESKY_MANAGED_ENABLED=true, talks to a Bluesky-compatible PDS admin API to create per-user accounts, issue app passwords, and store the linkage. Without managed mode, users connect their own Bluesky identifier and app password.
License
This repository is AGPL-3.0-only unless a file says otherwise.