site: give echo services its own page + navbar entry; frame it as a separate S2S-linked package, not native to the daemon
This commit is contained in:
parent
149ab69afe
commit
c4836c7dd1
7 changed files with 104 additions and 20 deletions
|
|
@ -1,15 +1,19 @@
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
**echoIRCd** is a modern IRC daemon and a full services suite, written from scratch in Rust. It is
|
**echoIRCd** is a modern IRC daemon, written from scratch in Rust. It is original code — not a fork
|
||||||
original code — not a fork of another ircd — and the entire tree compiles with
|
of another ircd — and the entire tree compiles with `#![forbid(unsafe_code)]`.
|
||||||
`#![forbid(unsafe_code)]`.
|
|
||||||
|
Accounts and channels are handled by **echo services**, a *separate* companion package that links
|
||||||
|
to the daemon over the server-to-server protocol — the daemon itself is a pure ircd and does not
|
||||||
|
have services built in.
|
||||||
|
|
||||||
## What you get
|
## What you get
|
||||||
|
|
||||||
- **echoIRCd** — the server: a single-threaded core with an epoll reactor pool, the full channel
|
- **echoIRCd** — the daemon: a single-threaded core with an epoll reactor pool, the full channel
|
||||||
and user mode set, host cloaking, connection classes, and an operator privilege model.
|
and user mode set, host cloaking, connection classes, and an operator privilege model. It exposes
|
||||||
- **echo services** — NickServ, ChanServ, OperServ, MemoServ and more, linked over a standard
|
the account and SASL *interface* that services plug into.
|
||||||
server-to-server protocol and backed by an event-sourced store.
|
- **echo services** — a separate package (NickServ, ChanServ, OperServ, MemoServ and more), linked
|
||||||
|
over the server-to-server protocol and backed by an event-sourced store.
|
||||||
|
|
||||||
## Highlights
|
## Highlights
|
||||||
|
|
||||||
|
|
|
||||||
10
src/main.rs
10
src/main.rs
|
|
@ -54,6 +54,12 @@ struct ConnectTemplate {
|
||||||
active: &'static str,
|
active: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "services.html")]
|
||||||
|
struct ServicesTemplate {
|
||||||
|
active: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
struct SidePage {
|
struct SidePage {
|
||||||
slug: &'static str,
|
slug: &'static str,
|
||||||
title: &'static str,
|
title: &'static str,
|
||||||
|
|
@ -95,6 +101,9 @@ async fn features() -> Response {
|
||||||
async fn connect() -> Response {
|
async fn connect() -> Response {
|
||||||
page(ConnectTemplate { active: "connect" })
|
page(ConnectTemplate { active: "connect" })
|
||||||
}
|
}
|
||||||
|
async fn services() -> Response {
|
||||||
|
page(ServicesTemplate { active: "services" })
|
||||||
|
}
|
||||||
|
|
||||||
async fn docs_index() -> Response {
|
async fn docs_index() -> Response {
|
||||||
Redirect::permanent(&format!("/docs/{}", docs::first_slug())).into_response()
|
Redirect::permanent(&format!("/docs/{}", docs::first_slug())).into_response()
|
||||||
|
|
@ -177,6 +186,7 @@ async fn main() {
|
||||||
.route("/", get(index))
|
.route("/", get(index))
|
||||||
.route("/features", get(features))
|
.route("/features", get(features))
|
||||||
.route("/connect", get(connect))
|
.route("/connect", get(connect))
|
||||||
|
.route("/services", get(services))
|
||||||
.route("/docs", get(docs_index))
|
.route("/docs", get(docs_index))
|
||||||
.route("/docs/search.json", get(docs_search))
|
.route("/docs/search.json", get(docs_search))
|
||||||
.route("/docs/:slug", get(docs_page))
|
.route("/docs/:slug", get(docs_page))
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,13 @@ code{font-family:var(--mono);font-size:.9em;background:rgba(18,165,148,.09);colo
|
||||||
.foot-links a{color:#aeb8c0;font-size:.9rem}
|
.foot-links a{color:#aeb8c0;font-size:.9rem}
|
||||||
.foot-links a:hover{color:#fff}
|
.foot-links a:hover{color:#fff}
|
||||||
|
|
||||||
|
/* services flow diagram */
|
||||||
|
.flow{display:flex;align-items:center;gap:.55rem;flex-wrap:wrap;margin:1.3rem 0 .3rem}
|
||||||
|
.flow .node{background:#fff;border:1px solid var(--line2);border-radius:9px;padding:.45rem .85rem;font-weight:500;font-size:.92rem}
|
||||||
|
.flow .node.accent{border-color:var(--teal);color:var(--teal-dd);background:var(--teal-t)}
|
||||||
|
.flow .node.accent2{border-color:#c6b6ec;color:#5a3fb0;background:#f3edfd}
|
||||||
|
.flow .arrow{color:var(--faint);font-family:var(--mono);font-size:.82rem}
|
||||||
|
|
||||||
@media(max-width:820px){
|
@media(max-width:820px){
|
||||||
.hero-in{grid-template-columns:1fr;gap:1.6rem}
|
.hero-in{grid-template-columns:1fr;gap:1.6rem}
|
||||||
.statuscard{max-width:26rem}
|
.statuscard{max-width:26rem}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{% block title %}echoIRCd — a from-scratch IRC server in Rust{% endblock %}</title>
|
<title>{% block title %}echoIRCd — a from-scratch IRC server in Rust{% endblock %}</title>
|
||||||
<meta name="description" content="echoIRCd is a modern IRC daemon and services suite, written from scratch in Rust — full IRCv3, modern TLS, SASL.">
|
<meta name="description" content="echoIRCd is a modern IRC daemon written from scratch in Rust — full IRCv3, modern TLS, SASL. Pairs with echo services, a separate package linked over S2S.">
|
||||||
<meta property="og:title" content="echoIRCd">
|
<meta property="og:title" content="echoIRCd">
|
||||||
<meta property="og:description" content="A from-scratch IRC server, written in Rust.">
|
<meta property="og:description" content="A from-scratch IRC server, written in Rust.">
|
||||||
<meta property="og:type" content="website">
|
<meta property="og:type" content="website">
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
<nav class="mainnav">
|
<nav class="mainnav">
|
||||||
<a href="/"{% if active == "home" %} class="on"{% endif %}>Home</a>
|
<a href="/"{% if active == "home" %} class="on"{% endif %}>Home</a>
|
||||||
<a href="/features"{% if active == "features" %} class="on"{% endif %}>Features</a>
|
<a href="/features"{% if active == "features" %} class="on"{% endif %}>Features</a>
|
||||||
|
<a href="/services"{% if active == "services" %} class="on"{% endif %}>Services</a>
|
||||||
<a href="/connect"{% if active == "connect" %} class="on"{% endif %}>Connect</a>
|
<a href="/connect"{% if active == "connect" %} class="on"{% endif %}>Connect</a>
|
||||||
<a href="/docs"{% if active == "docs" %} class="on"{% endif %}>Docs</a>
|
<a href="/docs"{% if active == "docs" %} class="on"{% endif %}>Docs</a>
|
||||||
<a href="https://orbit.devtronic.pro">Web client</a>
|
<a href="https://orbit.devtronic.pro">Web client</a>
|
||||||
|
|
@ -51,7 +52,7 @@
|
||||||
</svg>
|
</svg>
|
||||||
<span>echoIRCd</span>
|
<span>echoIRCd</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="foot-tag">A native-Rust IRC daemon & services. No forks, no C, no <code>unsafe</code>.</p>
|
<p class="foot-tag">A native-Rust IRC daemon, with <a href="/services">echo services</a> linked over S2S. No forks, no C, no <code>unsafe</code>.</p>
|
||||||
<nav class="foot-links">
|
<nav class="foot-links">
|
||||||
<a href="https://git.devtronic.pro/echo/echoIRCd">echoIRCd</a>
|
<a href="https://git.devtronic.pro/echo/echoIRCd">echoIRCd</a>
|
||||||
<a href="https://git.devtronic.pro/echo/echo">services</a>
|
<a href="https://git.devtronic.pro/echo/echo">services</a>
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="doc-block">
|
<div class="doc-block">
|
||||||
<h2>Services</h2>
|
<h2>Accounts & services</h2>
|
||||||
<ul>
|
<p>echoIRCd itself is only a daemon — it provides the account and SASL <em>interface</em> (the
|
||||||
<li><b>NickServ</b> — registration, grouped nicks, certificates, public keys, vhosts, profiles.</li>
|
SASL relay, the account extension, and U-lined service commands). Nickname registration,
|
||||||
<li><b>ChanServ</b> — founder/access, auto-op, akick, topic and mode locks.</li>
|
channels and the rest are handled by <a href="/services">echo services</a>, a separate
|
||||||
<li><b>OperServ · MemoServ · more</b> — network administration, offline messaging, and games.</li>
|
package linked over S2S — not built into the daemon.</p>
|
||||||
<li><b>Event-sourced</b> store; SASL relayed to services mechanism-agnostically.</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="doc-block">
|
<div class="doc-block">
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@
|
||||||
<section class="hero">
|
<section class="hero">
|
||||||
<div class="hero-in">
|
<div class="hero-in">
|
||||||
<div class="hero-main">
|
<div class="hero-main">
|
||||||
<p class="eyebrow">IRC daemon & services · written in Rust</p>
|
<p class="eyebrow">IRC daemon · written in Rust</p>
|
||||||
<h1>The from-scratch<br>IRC server.</h1>
|
<h1>The from-scratch<br>IRC server.</h1>
|
||||||
<p class="hero-sub">echoIRCd is a modern IRC daemon and a full services suite, built from the
|
<p class="hero-sub">echoIRCd is a modern IRC daemon, built from the ground up in Rust — full
|
||||||
ground up in Rust — full IRCv3, modern TLS, and SASL. No forks. No C. No <code>unsafe</code>.</p>
|
IRCv3, modern TLS, and SASL. No forks. No C. No <code>unsafe</code>. Pair it with
|
||||||
|
<a href="/services">echo services</a>, a separate package linked over S2S.</p>
|
||||||
<div class="cta">
|
<div class="cta">
|
||||||
<a class="btn btn-primary" href="/connect">Connect to the network</a>
|
<a class="btn btn-primary" href="/connect">Connect to the network</a>
|
||||||
<a class="btn btn-ghost" href="/features">See the features</a>
|
<a class="btn btn-ghost" href="/features">See the features</a>
|
||||||
|
|
@ -39,7 +40,7 @@
|
||||||
<div class="fcard"><h3>Full IRCv3</h3><p>server-time, message-tags, account-tag, batch, labeled-response, chathistory, multiline, standard-replies and more.</p></div>
|
<div class="fcard"><h3>Full IRCv3</h3><p>server-time, message-tags, account-tag, batch, labeled-response, chathistory, multiline, standard-replies and more.</p></div>
|
||||||
<div class="fcard"><h3>Modern TLS</h3><p>Direct TLS and WebSocket, OpenSSL & rustls backends, TLS 1.3 with post-quantum X25519MLKEM768, per-host SNI.</p></div>
|
<div class="fcard"><h3>Modern TLS</h3><p>Direct TLS and WebSocket, OpenSSL & rustls backends, TLS 1.3 with post-quantum X25519MLKEM768, per-host SNI.</p></div>
|
||||||
<div class="fcard"><h3>SASL, incl. ECDSA</h3><p>PLAIN, EXTERNAL, SCRAM-SHA-256, and ECDSA-NIST256P-CHALLENGE — sign a challenge, no password on the wire.</p></div>
|
<div class="fcard"><h3>SASL, incl. ECDSA</h3><p>PLAIN, EXTERNAL, SCRAM-SHA-256, and ECDSA-NIST256P-CHALLENGE — sign a challenge, no password on the wire.</p></div>
|
||||||
<div class="fcard"><h3>Native services</h3><p>NickServ, ChanServ, OperServ, MemoServ and more over S2S — accounts, channels, vhosts, an event-sourced store.</p></div>
|
<div class="fcard"><h3>Companion services</h3><p><a href="/services">echo services</a> is a <b>separate</b> package — NickServ, ChanServ and more — that links to the daemon over S2S. It is not built in.</p></div>
|
||||||
<div class="fcard"><h3>Anti-abuse built in</h3><p>A native security engine: connection & nick-flood detection, behavioral/content heuristics, DEFCON, DNSBL/MX screening.</p></div>
|
<div class="fcard"><h3>Anti-abuse built in</h3><p>A native security engine: connection & nick-flood detection, behavioral/content heuristics, DEFCON, DNSBL/MX screening.</p></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="h-center more"><a href="/features">Everything that's inside →</a></p>
|
<p class="h-center more"><a href="/features">Everything that's inside →</a></p>
|
||||||
|
|
|
||||||
63
templates/services.html
Normal file
63
templates/services.html
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Services — echoIRCd{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<section class="pagehead">
|
||||||
|
<div class="wrap">
|
||||||
|
<h1>echo services</h1>
|
||||||
|
<p>A companion services package that <b>links to echoIRCd over S2S</b>. It is <b>not</b> part of
|
||||||
|
the daemon — echoIRCd is a pure ircd; the services run as their own program.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="wrap doc">
|
||||||
|
<div class="doc-block">
|
||||||
|
<h2>Linked, not built in</h2>
|
||||||
|
<p>echoIRCd is an IRC <em>daemon</em> and nothing more. Accounts, nickname registration and
|
||||||
|
channel ownership are handled by <b>echo services</b> — a separate Rust program, from its own
|
||||||
|
repository, that connects to the network as a <b>linked services server</b>.</p>
|
||||||
|
<p>The split is deliberate: the daemon carries only the account and SASL <em>interface</em> (the
|
||||||
|
SASL relay, the account extension, and U-lined service commands); the services package holds
|
||||||
|
the accounts, the logic, and the data.</p>
|
||||||
|
<div class="flow">
|
||||||
|
<span class="node">IRC client</span><span class="arrow">↔</span>
|
||||||
|
<span class="node accent">echoIRCd</span><span class="arrow">↔ S2S ↔</span>
|
||||||
|
<span class="node accent2">echo services</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="doc-block">
|
||||||
|
<h2>The services</h2>
|
||||||
|
<div class="cards">
|
||||||
|
<div class="fcard"><h3>NickServ</h3><p>Register and protect your nick — grouped nicks, certificates, public keys, vhosts, and profiles.</p></div>
|
||||||
|
<div class="fcard"><h3>ChanServ</h3><p>Channel founders and access lists, auto-op, akick, and topic & mode locks.</p></div>
|
||||||
|
<div class="fcard"><h3>OperServ</h3><p>Network administration — akills, sessions, and staff tooling.</p></div>
|
||||||
|
<div class="fcard"><h3>MemoServ</h3><p>Leave messages for accounts while they're offline.</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="doc-block">
|
||||||
|
<h2>How it fits together</h2>
|
||||||
|
<ul>
|
||||||
|
<li>echo services connects to echoIRCd over the <b>server link</b> — the same server-to-server protocol servers use between each other.</li>
|
||||||
|
<li>The daemon <b>U-lines</b> the services server and names it as the SASL server, so its privileged commands and SASL relay are trusted.</li>
|
||||||
|
<li>SASL is relayed from the daemon to services <b>mechanism-agnostically</b>, so new mechanisms (like ECDSA) work with no daemon changes.</li>
|
||||||
|
<li>State is <b>event-sourced</b>: every change is an appended event, replayed to rebuild the database.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="doc-block">
|
||||||
|
<h2>Run & source</h2>
|
||||||
|
<p>echo services is its own binary, with its own configuration:</p>
|
||||||
|
<pre class="code">echo config.toml</pre>
|
||||||
|
<p>Source: <a href="https://git.devtronic.pro/echo/echo">git.devtronic.pro/echo/echo</a>. See the
|
||||||
|
docs on <a href="/docs/services">Services</a> and <a href="/docs/linking">Server links</a>.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="ctaband">
|
||||||
|
<div class="wrap ctaband-in">
|
||||||
|
<div><h2>Register your nick</h2><p class="mono-line">/msg NickServ REGISTER <password> <email></p></div>
|
||||||
|
<a class="btn btn-primary" href="/docs/accounts">Accounts & SASL</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue