Elektrine
Find a file
Maxfield Luke 047d32e58e
All checks were successful
Deploy Docker Images / Build, push, and deploy (push) Successful in 59s
ci: trigger deploy after Actions secrets restore
2026-07-30 02:06:27 -04:00
.forgejo ci: trigger deploy after Actions secrets restore 2026-07-30 02:06:27 -04:00
.github Initial commit 2026-07-30 01:36:18 -04:00
apps Initial commit 2026-07-30 01:36:18 -04:00
clients Initial commit 2026-07-30 01:36:18 -04:00
config Initial commit 2026-07-30 01:36:18 -04:00
deploy Initial commit 2026-07-30 01:36:18 -04:00
docs Initial commit 2026-07-30 01:36:18 -04:00
env Initial commit 2026-07-30 01:36:18 -04:00
external Initial commit 2026-07-30 01:36:18 -04:00
priv/repo Initial commit 2026-07-30 01:36:18 -04:00
release_builder Initial commit 2026-07-30 01:36:18 -04:00
scripts Initial commit 2026-07-30 01:36:18 -04:00
.credo.exs Initial commit 2026-07-30 01:36:18 -04:00
.dockerignore Initial commit 2026-07-30 01:36:18 -04:00
.env.example Initial commit 2026-07-30 01:36:18 -04:00
.formatter.exs Initial commit 2026-07-30 01:36:18 -04:00
.gitignore Initial commit 2026-07-30 01:36:18 -04:00
AGENTS.md Initial commit 2026-07-30 01:36:18 -04:00
CODE_OF_CONDUCT.md Initial commit 2026-07-30 01:36:18 -04:00
CONTRIBUTING.md Initial commit 2026-07-30 01:36:18 -04:00
elixir_buildpack.config Initial commit 2026-07-30 01:36:18 -04:00
LICENSE Initial commit 2026-07-30 01:36:18 -04:00
mise.toml Initial commit 2026-07-30 01:36:18 -04:00
mix.exs Initial commit 2026-07-30 01:36:18 -04:00
mix.lock Initial commit 2026-07-30 01:36:18 -04:00
phoenix_static_buildpack.config Initial commit 2026-07-30 01:36:18 -04:00
README.md Initial commit 2026-07-30 01:36:18 -04:00
SECURITY.md Initial commit 2026-07-30 01:36:18 -04:00

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 apps
  • clients/: client-side artifacts that are not shipped with the server release
  • config/: shared compile-time and runtime config
  • deploy/: Docker, Caddy, onion, and VPN deploy assets
  • docs/: architecture, protocol, API, and self-hosting docs
  • env/: example environment files
  • release_builder/: module-aware release build project
  • scripts/: 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 in lib/elektrine/components
  • apps/elektrine_web: endpoint, router, plugs, layouts, the ElektrineWeb.Components.UI design-system kit, and the account/admin shell
  • apps/arblarg: chat facade plus LiveViews, JSON APIs, and PAT APIs
  • apps/elektrine_social: timeline, communities, federation, social controllers, and LiveViews
  • apps/elektrine_email: mailbox, contacts, mail protocols, JMAP, WKD, and mail web routes
  • apps/elektrine_vpn: WireGuard management and VPN UI/API
  • apps/elektrine_nerve: Nerve domain and extracted routes
  • apps/elektrine_dns: managed DNS runtime, DNS API routes, and DNS LiveViews
  • apps/elektrine_uptime: uptime monitors, check history, incidents, and dashboard routes
  • apps/atomine: proofs, personhood, account trust, and credit policy domain logic
  • apps/kairo: capture, indexing, and graph-oriented knowledge features
  • apps/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/register while 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_MODULES controls which product modules are turned on
  • release builds default to that same module list
  • ELEKTRINE_RELEASE_MODULES still 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 only
  • mail: Elektrine mail protocols; production SMTP edge/delivery still needs a separate Haraka deployment
  • dns: optional authoritative DNS service enabled through the Docker dns profile
  • vpn: optional Docker-managed WireGuard on the same stack, with optional fleet mode
  • addons: Caddy edge, TURN, Bluesky PDS, onion hosting, and client artifacts

Start with:

  • docs/api/external-api.md
  • docs/self-hosting/README.md
  • docs/self-hosting/docker.md
  • docs/self-hosting/core.md
  • docs/self-hosting/caddy.md
  • docs/self-hosting/mail.md
  • docs/architecture/dns-module.md
  • docs/self-hosting/turn.md
  • docs/self-hosting/vpn.md
  • docs/addons/onion.md
  • docs/clients/nerve-extension.md
  • docs/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-haraka CI builds and pushes git.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 via configure_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.