Web Backends, Namespaces und Websockets!

Posted by luto on Monday, January 21, 2019

Seitdem es uberspace gibt, gibt es auch das gute, alte RewriteRule [P]. Damit lassen sich Services wie etherpad-lite über den Apache in die große, weite Welt schleusen. Das klappt in den meisten Fällen zwar ganz gut, hat aber das eine oder andere Manko.

Heute möchten wir euch ein neues Feature vorstellen, um all diese Mankos auf einen Schlag loszuwerden: unsere Web-Backends 🎉

tldr/english: our new uberspace web backend set command is now in opt-in beta. Read the docs to learn more. Also review the breaking changes.

Web-Backends

[isabell@philae ~]$ uberspace web backend set / --http --port 1024
Set backend for / to port 1024; please make sure something is listening!
You can always check the status of your backend using "uberspace web backend list".

[isabell@philae ~]$ uberspace web backend list
/ http:1024 => OK, listening: PID 42, nodejs

[isabell@philae ~]$ curl https://isabell.uber.space
Hello, nodejs!

So geht Backendeverwaltung. Statt händischen rumfummeln in .htaccess-Dateien haben wir uns etwas frisches, neues für euch ausgedacht: uberspace web backend. Durch diesen Befehl könnt ihr nun beliebig viele Backends, auf beliebigen Pfaden, beliebigen Domains zu beliebigen Applikationen durchschleifen. Im Hintergrund wird daraus ein proxy_pass in unserer nginx-Config. Das hat im Vergleich zu unserer bisherigen Apache-Bastellösung eine Menge Vorteile:

  • es ist verdammt schnell.
  • websockets kommen zu ihren Applikationen durch
  • X-Forwarded-Host fällt weg - und damit Bugs in vielen Apps
  • kein Apache, keine merkwürdige mod_rewrite-Syntax, keine 500er durch Tippfehler!
  • einfaches Debugging dank uberspace web backend list

Damit dieser Blogpost, was seine Länge angeht, im Rahmen bleibt, lassen wir die genaue Syntax und die Möglichkeiten mal außen vor - mehr Infos gibts im Manual.

Zusätzlich haben wir für die technisch interessierten unter euch dort eine neue Rubrik ins Leben gerufen: Background. In Zukunft werden sich dort Artikel mit Hintergründen und Implementationsdetails zu unseren Setup finden - ein bisschen wie das frühere U6-Wiki. Initial haben wir sie mit zwei Artikeln bestückt; der erste behandelt unseren HTTP-Stack.

Dieses Feature ist momentan in einer semi-offenen Betaphase. Der Code ist auf allen Hosts ausgerollt, der uberspace web backend-Befehl aber nicht für alle uberspaces freigeschalten. Bitte schick uns eine kurze Mail an hallo@uberspace.de, wenn du Interesse hast, beim Testen zu helfen.

Netzwerk

            _
          (`  ).              .---Host:-stardust--.              .-----user@stardust--.
         (     ).             |                   |              |                    |
        _(       '`.          |       veth_user_o >===internal===> veth_user          |
    .=(`( Internet )          |        100.64.9.1 |              |  100.64.9.2        |
    ((    (..__.:'-' ===WAN===> eth0              |              | lo                 |
    `(       ) )              | 185.26.156.62     |              |  127.0.0.1         |
      ` __.:'   )             |                   |              |                    |
             --'              \-------------------/              \--||-----||-----||--/
                                                                    ||     ||     ||
                                                                    \/     \/     \/
.                                                                 nodejs  nginx  gogs

Dieses Feature zu bauen hat eine ganze Weile gedauert. Nicht, weil nginx-Config zu kompliziert ist, sondern weil uns noch etwas Vorarbeit gefehlt hat. Im Laufe der Entwicklung haben wir unser Netzwerk-Setup innerhalb der Hosts auf den Kopf gestellt: jeder uberspace bekommt nun einen eigenen TCP/IP-Stack und damit eigene veth und lo-Interfaces. Das ist nicht nur technisch schick, sondern hat auch zwei für das Feature wichtige Implikationen:

  1. jeder uberspace kann einen Service auf Port 9100 starten - es gibt keine Kollisionen mehr.
  2. da nun jeder Uberspace eine eigene IP-Adresse hat, können wir die Ports bzw. Services im nginx (und später in der Firewall, für Portfreischaltungen!) sehr viel einfacher zuordnen.

Im Hintergrund arbeiten wir hier mit Network Namespaces. Viele Details, Erklärungen und Code-Schnipsel dazu lassen sich im Manual finden. Ein Besuch lohnt sich!

Breaking Changes

Mit tiefgreifenden Änderungen geht auch mal etwas bestehendes kaputt. Für die meisten der entstehenden Probleme haben wir uns Automatismen ausgedacht. Du musst also im besten Fall gar nichts unternehmen. Manche Themen können wir allerdings nicht abfangen - dort heißt es Hand anlegen:

  1. Ein uberspace hat in Zukunft ein eigenes Loopback-Interface und damit ein unabhängiges 127.0.0.1. Wenn deine Services nur darauf lauschen, sind sie für die Web-Backends aber auch .htaccess-Proxies nicht erreichbar. Abhilfe schafft 0.0.0.0 (d.h. alle Interfaces) als Lauschpunkt.

Wir werden dich per Mail über inkorrekt konfigurierte Services informieren, Umstellen musst du sie allerdings selbst; gerne auch schon vor dem Update. 2. Ein RewriteRule (.*) http://127.0.0.1:1234/$1 [P] versucht sich am Loopback-Interface des Apachen. Dort ist dein Service allerdings nicht (mehr) zu finden. Verwende stattdessen Web-Backends.

Bestehende Proxies werden von uns automatisch mit einer Zwischenlösung versorgt. Es geht also nichts kaputt, wenn auf 0.0.0.0 gelauscht wird. 3. Direkte TCP/UDP-Verbindungen zwischen uberspaces werden nicht mehr unterstützt. Du kannst stattdessen via SSH port forwarding einen Tunnel aufbauen.

Wann denn?

Die Web-Backends und die Namespaces sind wie Eingangs erwähnt bereits in der Beta-Phase. Wenn du Lust hast, uns beim Testen zu helfen, schreib uns gerne ein Mail an hallo@uberspace.de!

Sobald wir mit dem Testergebnis zufrieden sind, kommen die Neuerungen in den nächsten Wochen natürlich auf alle U7 uberspaces. Hab ein Auge auf unser Blog und @ubernauten auf Twitter für Details!


Die ASCII-Wolke von asciiart.eu hat a:f gemalt. Danke!