Skip to content

feat: systemd socket activation support (LISTEN_FDS auto-detect) #66

Description

@dmaugis

When gemini-web2api is managed by systemd's socket activation (.socket unit), systemd passes an already-bound socket as FD 3. The process must not call bind() or it fails with EADDRINUSE. This patch detects the activation environment and uses socket.fromfd() instead.

+19 lines / -2 lines — zero flags, zero config. If LISTEN_FDS is absent, behaviour is identical.

diff :
diff
diff --git a/gemini_web2api.py b/gemini_web2api.py
index 3cd6f4b..8b49560 100644
--- a/gemini_web2api.py
+++ b/gemini_web2api.py
@@ -32,6 +32,7 @@ import os
import hashlib
import argparse
import base64
+import socket
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn

@@ -865,8 +866,26 @@ def main():
allow_reuse_address = True

 port = CONFIG["port"]
  • server = ThreadedServer((CONFIG["host"], port), GeminiHandler)
  • print(f"gemini-web2api v{version}")
  • listen_fds = os.environ.get("LISTEN_FDS")
  • listen_pid = os.environ.get("LISTEN_PID")
  • if listen_fds and listen_pid and int(listen_pid) == os.getpid() and int(listen_fds) > 0:
  •    fd = 3
    
  •    try:
    
  •        sockinfo = socket.fromfd(fd, socket.AF_INET6, socket.SOCK_STREAM).getsockname()
    
  •        fam = socket.AF_INET6 if len(sockinfo) == 4 else socket.AF_INET
    
  •    except OSError:
    
  •        fam = socket.AF_INET
    
  •    sock = socket.fromfd(fd, fam, socket.SOCK_STREAM)
    
  •    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
  •    server = ThreadedServer((CONFIG["host"], port), GeminiHandler, bind_and_activate=False)
    
  •    server.socket = sock
    
  •    server.server_address = (CONFIG["host"], port)
    
  •    print(f"gemini-web2api v{__version__} (systemd socket activation)")
    
  • else:
  •    server = ThreadedServer((CONFIG["host"], port), GeminiHandler)
    
  •    print(f"gemini-web2api v{__version__}")
    

Labels : enhancement

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions