{"id":13879653,"url":"https://github.com/digital-fabric/tipi","last_synced_at":"2025-04-04T06:10:11.678Z","repository":{"id":39693348,"uuid":"232424689","full_name":"digital-fabric/tipi","owner":"digital-fabric","description":"Tipi - the All-in-one Web Server for Ruby Apps","archived":false,"fork":false,"pushed_at":"2024-02-28T23:01:16.000Z","size":496,"stargazers_count":243,"open_issues_count":5,"forks_count":6,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-28T05:12:15.303Z","etag":null,"topics":["acme","acme-client","http","http-server","http2","https","polyphony","rack","ruby","ssl","tls","web-server","websocket"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digital-fabric.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"noteflakes"}},"created_at":"2020-01-07T21:54:57.000Z","updated_at":"2025-03-17T21:33:23.000Z","dependencies_parsed_at":"2023-07-14T19:08:57.037Z","dependency_job_id":"e192b92c-d8ad-47da-9ba9-5bf44c9f183e","html_url":"https://github.com/digital-fabric/tipi","commit_stats":{"total_commits":386,"total_committers":9,"mean_commits":"42.888888888888886","dds":0.1476683937823834,"last_synced_commit":"093fbadfb872daac8a8c755ee3c4ca3afd1a7e1f"},"previous_names":["digital-fabric/polyphony-http"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digital-fabric%2Ftipi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digital-fabric%2Ftipi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digital-fabric%2Ftipi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digital-fabric%2Ftipi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digital-fabric","download_url":"https://codeload.github.com/digital-fabric/tipi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247128753,"owners_count":20888235,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acme","acme-client","http","http-server","http2","https","polyphony","rack","ruby","ssl","tls","web-server","websocket"],"created_at":"2024-08-06T08:02:27.840Z","updated_at":"2025-04-04T06:10:11.655Z","avatar_url":"https://github.com/digital-fabric.png","language":"Ruby","funding_links":["https://github.com/sponsors/noteflakes"],"categories":["Ruby"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"docs/tipi-logo.png\" /\u003e\u003c/p\u003e\n\n# Tipi - the All-in-one Web Server for Ruby Apps\n\n[![Gem Version](https://badge.fury.io/rb/tipi.svg)](http://rubygems.org/gems/tipi)\n[![Tipi Test](https://github.com/digital-fabric/tipi/workflows/Tests/badge.svg)](https://github.com/digital-fabric/tipi/actions?query=workflow%3ATests)\n[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/digital-fabric/tipi/blob/master/LICENSE)\n\n## What is Tipi?\n\nTipi is an integrated, feature-complete HTTP/S server for Ruby applications.\nTipi is built on top of\n[Polyphony](https://github.com/digital-fabric/polyphony), a robust,\nhigh-performance library for building highly-concurrent applications in Ruby.\nTipi can be used to serve any Rack application or set of static files directly\nwithout having to employ a reverse-proxy such as Nginx.\n\n## Features\n\n* High-performance, highly concurrent web server based on\n  [Polyphony](https://github.com/digital-fabric/polyphony)\n* Full support for HTTP/1, HTTP/2, WebSocket protocols\n* Built-in SSL termination for secure, encrypted connections\n* **Automatic SSL certificates** using ACME providers such as Let's Encrypt (WIP)\n* Automatic ALPN protocol selection for serving HTTP/2\n* Request and response body streaming for efficient downloads and uploads\n* Full support for Rack-based apps\n\n## Benchmarks\n\n\u003e Caveat emptor: the following results were obtained with an ad-hoc, manual\n\u003e process. I am not really familiar with the servers I compared Tipi against,\n\u003e and I ran them in their default configuration (apart from setting the number\n\u003e of workers). Take these results with a bunch of salt.\n\n\u003cimg src=\"bm.png\" style=\"width: 480px\"\u003e\n\n| |Tipi|Puma|Falcon|Unicorn|\n|-|---:|---:|-----:|------:|\n|HTTP/1.1|138629|34573|40714|7438|\n|HTTPS/2|56762|n/a|34226|n/a|\n\n### Methodology\n\n- All servers ran the same \"Hello world\" [Rack\n  application](https://github.com/digital-fabric/tipi/blob/master/examples/hello.ru)\n- Each server was run with 4 forked worker processes:\n  - Tipi: `tipi -w4 -flocalhost:10080:10443 examples/hello.ru`\n  - [Puma](https://github.com/puma/puma): `puma -w 4 examples/hello.ru`\n  - [Falcon](https://github.com/socketry/falcon/): `falcon -n 4 -b http://localhost:9292/ -c examples/hello.ru`\n  - [Unicorn](https://yhbt.net/unicorn/): `unicorn -c u.conf examples/hello.ru`\n    with the configuration file containing the directive `worker_processes 4`\n- The benchmark results were obtained using `wrk -d60 -t4 -c64 \u003curl\u003e`\n- All servers were run on Ruby 2.7.2p137\n- Machine specs: i5-8350U@1.7GHzx8 CPU, 8GB of RAM, running Linux kernel version 5.13.7\n- Puma does not support HTTP/2.\n- As far as I could tell Unicorn does not support SSL termination.\n\n## Running Tipi\n\nTo run Tipi, run the included `tipi` command. Alternatively you can add tipi as\na dependency to your Gemfile, then run `bundle exec tipi`. By default \n\nTipi can be used to drive Rack apps or alternatively any app using the\n[Qeweney](https://github.com/digital-fabric/qeweney) request-response interface.\n\n### Running Rack apps\n\nUse the `tipi` command to start your app:\n\n```bash\n$ bundle exec tipi myapp.ru\n```\n\n### Running Qeweney apps\n\n```bash\n$ bundle exec tipi myapp.rb\n```\n\nThe app script file should define an `app` method that returns a proc/lambda\ntaking a single `Qeweney::Request` argument. Here's an example:\n\n```ruby\n# frozen_string_literal: true\n\ndef app\n  -\u003e(req) { req.respond('Hello, world!', 'Content-Type' =\u003e 'text/plain') }\nend\n```\n\n## Setting server listening options\n\nBy default, Tipi serves plain HTTP on port 1234, but you can easily change that\nby providing command line options as follows:\n\n### HTTP\n\nTo listen for plain HTTP, use the `-l`/`--listen` option and specify a port\nnumber:\n\n```bash\n$ bundle exec tipi -l9292 myapp.ru\n```\n\n### HTTPS\n\nTo listen for HTTPS connections, use the `-s`/`--secure` option and specify a\nhost name and a port:\n\n```bash\n$ bundle exec tipi -sexample.com:9292 myapp.ru\n```\n\n### Full service listening\n\nThe Tipi full service listens for both HTTP and HTTPS and supports automatic\ncertificate provisioning. To use the full service, use the `-f`/`--full` option,\nand specify the domain name, the HTTP port, and the HTTPS port, e.g.:\n\n```bash\n$ bundle exec tipi -fmysite.org:10080:10443 myapp.ru\n\n#If serving multiple domains, you can use * as place holder\n$ bundle exec tipi -f*:10080:10443 myapp.ru\n```\n\nIf `localhost` is specified as the domain, Tipi will automatically generate a\nlocalhost certificate.\n\n## Concurrency settings\n\nBy default, the `tipi` command starts a single controller and uses\n[Polyphony](https://github.com/digital-fabric/polyphony) to run each connection\non its own fiber. This means that you will have a single process running on a\nsingle thread (on a single CPU core). In order to parallelize your app and\nemploy multiple CPU cores, you can tell Tipi to fork multiple worker processes\nto run your app. The number of workers is controlled using the `-w`/`--workers`\noption:\n\n```bash\n# fork 4 worker processes\n$ bundle exec tipi -w4 myapp.ru\n```\n\nYou can also set Tipi to spawn multiple threads in each worker when in\ncompatibility mode (see below.)\n\n## Compatibility mode\n\n\u003e Note: compatibility mode is still being developed, and currently only supports\n\u003e HTTP/1 connections.\n\nIn some apps, using Polyphony is not possible, due to incompatibilities between\nit and other third-party dependencies. In order to be able to run these apps,\nTipi provides a compatibility mode that does not use Polyphony for concurrency,\nbut instead uses a thread-per-connection concurrency model. You can also fork\nmultiple workers, each running multiple threads, if so desired. Note that the\nconcurrency level is the maximum number workers multiplied by the number of\nthreads per worker:\n\n```\nconcurrency = worker_count * threads_per_worker\n```\n\nTo run Tipi in compatibility mode, use the `-c`/`--compatibility` option, e.g.:\n\n```bash\n# 4 workers * 8 threads = 32 max concurrency\n$ bundle exec tipi -c -w4 -t8 myapp.ru\n```\n\n## Worker process supervision\n\nTipi employs a supervisor-controller-worker process supervision model, which\nminimizes the memory consumption of forked workers, and which facilitates\ngraceful reloading after updating the application code.\n\nThis supervision model is made of three levels:\n\n- Supervisor - Starts and stops the controller process\n- Controller - loads the application code and forks workers\n- Worker - listens for connections, handles incoming requests\n\n(If the worker count is 1, the Controller and Worker roles are merged into a\nsingle process.)\n\nThis model allows Tipi to fork workers after loading the app code, and use a\nmuch simpler way to perform graceful restarts:\n\n- The supervisor starts a new controller process (which may fork one or more\n  worker processes).\n- Sleep for a certain amount of time (currently 1 second.)\n- Stop the old controller process.\n- Each worker process is gracefully stopped and allowed to finish all pending\n  requests, then shutdown all open connections.\n  \n## Performing a graceful restart\n\nA graceful restart performed by sending `SIGUSR2` to the supervisor process.\n\n## Documentation\n\nDocumentation for Tipi's API is coming soon...\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigital-fabric%2Ftipi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigital-fabric%2Ftipi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigital-fabric%2Ftipi/lists"}