itsi-server 0.2.27.rc1-x86_64-linux → 0.2.27-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e16f9c96d5e04d3f7d4d1677d029e29ff9de945d31ab252db520ddafa734767b
4
- data.tar.gz: a43a8b24ed433bd79017fb24a6073ff953d13927687e7349e845686b02918974
3
+ metadata.gz: fad0f86c8e82c6bc2772407608124aaaccac0f4f80b0a652267978a020881089
4
+ data.tar.gz: dd9c0f043baf59043560fda020ed4e1ed190d2ce2a6c45c9412f23d4596e680e
5
5
  SHA512:
6
- metadata.gz: 94335b92eb34045bfacd21e7e9e4b71b7b140cfda09970668eda5276edd17646a556ee0b9f1280307b225d3b1657021db84f342167d05c1b3481731887cee498
7
- data.tar.gz: f98a7aa4a87337b034d1a891adbf741d3bd49d58a718f3102aa9c129fcda6e9b80155fedb1b0925dbc63b97eb4c238162f61a7a35c9724a0e4204825c58e3fc5
6
+ metadata.gz: 825097e5f3bc540cf3e752f9ffe21264663a7fc9e4a2058fac7a3b90046bab1d7f96b525de0f69be580752d758d22f32078e0726f857c1d7238d3606624e0263
7
+ data.tar.gz: dda9041982ace348303f9469f7013cab21449e7185fd43b8b8efd4caac5456a047914d2987097ca63e06de7127ba0133ae6e819c62dc8b9644fe5a35caa21b99
data/Cargo.lock CHANGED
@@ -1662,7 +1662,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
1662
1662
 
1663
1663
  [[package]]
1664
1664
  name = "itsi-server"
1665
- version = "0.2.27-rc1"
1665
+ version = "0.2.27"
1666
1666
  dependencies = [
1667
1667
  "argon2",
1668
1668
  "async-channel",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-scheduler"
3
- version = "0.2.27-rc1"
3
+ version = "0.2.27"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-server"
3
- version = "0.2.27-rc1"
3
+ version = "0.2.27"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -11,7 +11,6 @@ use http::{request::Parts, Response, StatusCode};
11
11
  use http_body_util::BodyExt;
12
12
  use itsi_error::CLIENT_CONNECTION_CLOSED;
13
13
  use itsi_rb_helpers::{print_rb_backtrace, HeapValue};
14
- use itsi_tracing::debug;
15
14
  use magnus::{
16
15
  block::Proc,
17
16
  error::{ErrorType, Result as MagnusResult},
@@ -72,6 +72,17 @@ pub enum ResponseFrame {
72
72
  }
73
73
 
74
74
  impl ItsiHttpResponse {
75
+ fn is_expected_bridge_shutdown(err: &io::Error) -> bool {
76
+ matches!(
77
+ err.kind(),
78
+ io::ErrorKind::BrokenPipe
79
+ | io::ErrorKind::ConnectionAborted
80
+ | io::ErrorKind::ConnectionReset
81
+ | io::ErrorKind::NotConnected
82
+ | io::ErrorKind::UnexpectedEof
83
+ )
84
+ }
85
+
75
86
  pub fn new(
76
87
  parts: Arc<Parts>,
77
88
  response_sender: OneshotSender<ResponseFrame>,
@@ -98,13 +109,17 @@ impl ItsiHttpResponse {
98
109
  let (mut cr, mut cw) = tokio::io::split(client_io);
99
110
 
100
111
  let to_ruby = tokio::spawn(async move {
101
- if let Err(e) = tokio::io::copy(&mut cr, &mut lw).await {
102
- eprintln!("Error copying upgraded->local: {:?}", e);
112
+ if let Err(err) = tokio::io::copy(&mut cr, &mut lw).await {
113
+ if !Self::is_expected_bridge_shutdown(&err) {
114
+ eprintln!("Error copying upgraded->local: {:?}", err);
115
+ }
103
116
  }
104
117
  });
105
118
  let from_ruby = tokio::spawn(async move {
106
- if let Err(e) = tokio::io::copy(&mut lr, &mut cw).await {
107
- eprintln!("Error copying upgraded->local: {:?}", e);
119
+ if let Err(err) = tokio::io::copy(&mut lr, &mut cw).await {
120
+ if !Self::is_expected_bridge_shutdown(&err) {
121
+ eprintln!("Error copying local->upgraded: {:?}", err);
122
+ }
108
123
  }
109
124
  });
110
125
 
@@ -63,7 +63,7 @@ pub fn send_lifecycle_event(event: LifecycleEvent) {
63
63
  }
64
64
  }
65
65
 
66
- fn receive_signal(signum: i32, _: sighandler_t) {
66
+ extern "C" fn receive_signal(signum: i32) {
67
67
  debug!("Received signal: {}", signum);
68
68
  SIGINT_COUNT.fetch_add(-1, Ordering::SeqCst);
69
69
  let event = match signum {
@@ -96,20 +96,25 @@ fn receive_signal(signum: i32, _: sighandler_t) {
96
96
  }
97
97
  }
98
98
 
99
+ fn signal_handler() -> sighandler_t {
100
+ receive_signal as *const () as sighandler_t
101
+ }
102
+
99
103
  pub fn reset_signal_handlers() -> bool {
100
104
  debug!("Resetting signal handlers");
101
105
  SIGINT_COUNT.store(0, Ordering::SeqCst);
102
106
  SHUTDOWN_REQUESTED.store(false, Ordering::SeqCst);
103
107
 
104
108
  unsafe {
105
- libc::signal(libc::SIGTERM, receive_signal as usize);
106
- libc::signal(libc::SIGINT, receive_signal as usize);
107
- libc::signal(libc::SIGUSR2, receive_signal as usize);
108
- libc::signal(libc::SIGUSR1, receive_signal as usize);
109
- libc::signal(libc::SIGHUP, receive_signal as usize);
110
- libc::signal(libc::SIGTTIN, receive_signal as usize);
111
- libc::signal(libc::SIGTTOU, receive_signal as usize);
112
- libc::signal(libc::SIGCHLD, receive_signal as usize);
109
+ let handler = signal_handler();
110
+ libc::signal(libc::SIGTERM, handler);
111
+ libc::signal(libc::SIGINT, handler);
112
+ libc::signal(libc::SIGUSR2, handler);
113
+ libc::signal(libc::SIGUSR1, handler);
114
+ libc::signal(libc::SIGHUP, handler);
115
+ libc::signal(libc::SIGTTIN, handler);
116
+ libc::signal(libc::SIGTTOU, handler);
117
+ libc::signal(libc::SIGCHLD, handler);
113
118
  }
114
119
  true
115
120
  }
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -54,12 +54,40 @@ Let's Encrypt enforces strict rate limits on production certificate generation.
54
54
  {{< /callout >}}
55
55
 
56
56
 
57
- {{< callout type="warn" >}}
58
- Currently only the TLS-ALPN-01 challenge type is supported for automated certificates.
59
- The HTTP-01 challenge is not *yet* supported. This means that, for e.g. if your server is sitting behind a CDN or reverse proxy that performs HTTPS termination, you will not be able to rely on the *automated* certificate generation for fully automated, verified e2e encryption.
60
-
61
- Instead you may wish to use:
62
- * [Self-signed](#development--self-signed) certificates
63
- * [Manually](#existing-certificates) install certificates
64
- * Use HTTP between the CDN and the server
65
- {{< /callout >}}
57
+ Itsi supports both ACME challenge types that matter for common deployments:
58
+
59
+ * `TLS-ALPN-01` is used when the certificate authority can reach Itsi directly on the HTTPS listener.
60
+ * `HTTP-01` can be used when you also expose a reachable HTTP listener for the same hostname. In real Let's Encrypt deployments this typically means port `80` must reach Itsi for `/.well-known/acme-challenge/*`.
61
+
62
+ This means setups behind a CDN, WAF, or TLS-terminating proxy can still use automated certificates, provided plain HTTP validation traffic is forwarded to Itsi.
63
+
64
+ E.g. a production configuration that allows HTTP-01 fallback might look like this:
65
+
66
+ ```ruby {filename=Itsi.rb}
67
+ bind "http://0.0.0.0:80"
68
+ bind "https://0.0.0.0:443?cert=acme&domains=example.com&acme_email=you@example.com"
69
+ ```
70
+
71
+ ## Dynamic Domain Registration
72
+ You can add or remove ACME-managed domains while Itsi is already running.
73
+
74
+ This is useful when hostnames are discovered dynamically by your Ruby application, or when you want to defer certificate issuance until a tenant, customer, or site is activated.
75
+
76
+ Runtime APIs:
77
+
78
+ * `Itsi::Server.tls_bindings`
79
+ * `Itsi::Server.tls_domains(listener_id = nil)`
80
+ * `Itsi::Server.tls_domain_statuses(listener_id = nil)`
81
+ * `Itsi::Server.register_tls_domain(domain, listener_id = nil)`
82
+ * `Itsi::Server.unregister_tls_domain(domain, listener_id = nil)`
83
+
84
+ Example:
85
+
86
+ ```ruby
87
+ Itsi::Server.register_tls_domain("customer-a.example.com")
88
+
89
+ status = Itsi::Server.tls_domain_statuses.find { |entry| entry["domain"] == "customer-a.example.com" }
90
+ puts status
91
+ ```
92
+
93
+ When using dynamic issuance with HTTP-01, the same requirement still applies: the domain being issued must be able to reach an Itsi-managed HTTP listener for the ACME challenge path.
@@ -7,6 +7,8 @@ This allows Itsi to process a very large number of IO heavy requests concurrentl
7
7
 
8
8
  Enabling Fiber Scheduler mode can drastically improve application performance if you perform large amounts of blocking IO operations.
9
9
 
10
+ Itsi's bundled scheduler is intended to be practical for real Ruby applications, not just toy socket examples. It integrates with the scheduler hooks used by modern Rubies for socket I/O, DNS lookups, sleeps and timeouts, and process waiting.
11
+
10
12
 
11
13
  ## Configuration File
12
14
  ```ruby {filename="Itsi.rb"}
@@ -37,6 +37,10 @@ fiber_scheduler nil
37
37
  # bind "https://itsi.fyi?cert=acme&acme_email=admin@itsi.fyi"
38
38
  # You can generate certificates for multiple domains at once, by passing a comma-separated list of domains
39
39
  # bind "https://0.0.0.0?domains=foo.itsi.fyi,bar.itsi.fyi&cert=acme&acme_email=admin@itsi.fyi"
40
+ # If HTTPS on 443 is not directly reachable, you can also expose an HTTP listener and
41
+ # Let's Encrypt will be able to validate using HTTP-01 instead.
42
+ # bind "http://0.0.0.0:80"
43
+ # bind "https://0.0.0.0:443?domains=foo.itsi.fyi&cert=acme&acme_email=admin@itsi.fyi"
40
44
  #
41
45
  # If you already have a certificate you can specify it using the cert and key parameters
42
46
  # bind "https://itsi.fyi?cert=/path/to/cert.pem&key=/path/to/key.pem"
@@ -103,7 +103,8 @@ module Itsi
103
103
  elsif body_streamer
104
104
  # If we're partially hijacked or returned a streaming body,
105
105
  # stream this response.
106
- body_streamer.call(response)
106
+ stream = status == 101 ? request.partial_hijack : response
107
+ body_streamer.call(stream)
107
108
 
108
109
  elsif body.is_a?(Array)
109
110
  if body.length == 1
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Itsi
4
4
  class Server
5
- VERSION = "0.2.27.rc1"
5
+ VERSION = "0.2.27"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itsi-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.27.rc1
4
+ version: 0.2.27
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - Wouter Coppieters
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-06-14 00:00:00.000000000 Z
11
+ date: 2026-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json