{"id":44645643,"url":"https://github.com/nixpig/joubini","last_synced_at":"2026-02-14T19:33:44.225Z","repository":{"id":215577723,"uuid":"730031015","full_name":"nixpig/joubini","owner":"nixpig","description":"🐙 A super-simple to configure HTTP/S reverse proxy for local dev.","archived":false,"fork":false,"pushed_at":"2024-04-24T06:37:29.000Z","size":651,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-10T06:49:40.591Z","etag":null,"topics":["featured","network","networking","proxy","proxy-server","reverse-proxy","rust","rust-lang"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/nixpig.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2023-12-11T03:41:47.000Z","updated_at":"2025-08-16T08:22:42.000Z","dependencies_parsed_at":"2024-01-28T06:25:19.618Z","dependency_job_id":"a1bd3737-733b-487a-98aa-829409a592e2","html_url":"https://github.com/nixpig/joubini","commit_stats":null,"previous_names":["nixpig/joubini"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nixpig/joubini","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixpig%2Fjoubini","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixpig%2Fjoubini/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixpig%2Fjoubini/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixpig%2Fjoubini/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nixpig","download_url":"https://codeload.github.com/nixpig/joubini/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixpig%2Fjoubini/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29453471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T15:52:44.973Z","status":"ssl_error","status_checked_at":"2026-02-14T15:52:11.208Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["featured","network","networking","proxy","proxy-server","reverse-proxy","rust","rust-lang"],"created_at":"2026-02-14T19:33:44.038Z","updated_at":"2026-02-14T19:33:44.220Z","avatar_url":"https://github.com/nixpig.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Workflow Status](https://github.com/nixpig/joubini/actions/workflows/general.yml/badge.svg?branch=main)](https://github.com/nixpig/joubini/actions/workflows/general.yml?query=branch%3Amain)\n[![Coverage Status](https://coveralls.io/repos/github/nixpig/joubini/badge.svg?branch=main)](https://coveralls.io/github/nixpig/joubini?branch=main)\n\n# 🐙 joubini\n\nA super-simple and minimally configurable HTTP reverse proxy for local development with support for HTTP/1.1, HTTP/2, TLS/SSL and web sockets.\n\n![Screenshot of Joubini running as reverse proxy](screenshot.png)\n\n## ⚠️ WORK IN PROGRESS\n\nThis is a **work in progress**. It's not stable, it's not secure, and performance isn't great.\n\nAt this time, I wouldn't recommend using this for anything more than playing around. If you're looking for something production-ready, there are plenty of [good alternatives](#Alternatives) out there.\n\n## Features\n\n- [x] Support for clients using HTTP/1.1\n- [x] Support for clients using HTTP/2\n- [x] Support for TLS/SSL (HTTPS)\n- [x] Adds client `ip:port` to `x-forwarded-for` header\n- [x] Removes hop-by-hop headers (as defined in [RFC2616](https://datatracker.ietf.org/doc/html/rfc2616#section-13.5.1)) by default\n- [ ] Support for connection pooling\n- [ ] Support for web sockets\n- [ ] Optionally don't remove hop-by-hop headers?\n- [ ] Support for on-the-fly creation of SSL certificates\n\n## Usage\n\n```shell\n$ joubini --help\n\nA super-simple and minimally configurable HTTP reverse proxy for local development with support for HTTP/1.1, HTTP/2, TLS/SSL and web sockets.\n\nUsage: joubini [OPTIONS]\n\nOptions:\n  -H, --host \u003chost\u003e           Hostname or IP [default: 127.0.0.1]\n  -P, --port \u003clocal_port\u003e     Local port for reverse proxy server to listen on [default: 80]\n  -p, --proxy \u003cproxy_config\u003e  Configuration for proxy in format '\u003c:local_port?\u003e\u003c/local_path?\u003e\u003c:remote_port!\u003e\u003c/remote_path?\u003e'\n  -C, --config \u003cconfig_file\u003e  Path to configuration file\n  -T, --tls                   Serve over TLS\n      --pem \u003cPEM\u003e             Path to SSL certificate as `.pem` or `.crt`. Required if `--tls` flag is enabled.\n      --key \u003cKEY\u003e             Path to SSL certificate key as `.key`. Required if `--tls` flag is enabled.\n  -h, --help                  Print help\n  -V, --version               Print version\n\n```\n\n### Note\n\nOrdering of proxy configurations matters.\n\n❌ This **will not** work as (probably) intended:\n`joubini --proxy=myapp/api:3001/api --proxy=myapp:3000/ui`\n\n✅ This **will** work as (probably) intended:\n`joubini --proxy=myapp:3000/ui --proxy=myapp/api:3001/api`\n\n### Config file (optional)\n\nIf a config file is provided then no other provided CLI arguments will be parsed.\n\nProxies defined in the config file follow the same pattern as via CLI, i.e.\n\n`\u003c/local_path?\u003e\u003c:remote_port!\u003e\u003c/remote_path?\u003e`\n\n```yaml\n# joubini.yml\nport: 7878\nhost: localhost\ntls: true\npem: /tmp/localhost.crt\nkey: /tmp/localhost.key\nproxies:\n  - :3000 # http://127.0.0.1 -\u003e http://127.0.0.1:3000\n  - api:3001/api # http://127.0.0.1/api -\u003e http://127.0.0.1:3001/api\n  - admin:3002/dashboard # http://127.0.0.1/admin -\u003e http://127.0.0.1:3002/dashboard\n  - db:5432 # http://127.0.0.1/db -\u003e http://127.0.0.1:5432\n```\n\n### Examples\n\nSome common use cases are shown below. Combinations of these and other more complex use cases can be achieved, so see the more detailed documentation.\n\n#### Simple host to port mapping\n\n`http://127.0.0.1/*` 🠮 `http://127.0.0.1:3000/*`\n\n```shell\njoubini -p \":3000\"\n```\n\n#### Host path to port mapping\n\n`http://127.0.0.1/api/*` 🠮 `http://127.0.0.1:3001/*`\n\n```shell\njoubini -p \"api:3001\"\n```\n\n#### Host path to port/path mapping\n\n`http://127.0.0.1/admin/*` 🠮 `http://127.0.0.1:3002/admin/*`\n\n```shell\njoubini -p \"admin:3002/admin\"\n```\n\n#### Combine multiple configurations\n\n```shell\njoubini -p \":3000\" -p \"api:3001\" -p \"admin:3002/admin\"\n```\n\n#### Serve connection over TLS (SSL)\n\n```shell\njoubini \\\n  --tls \\\n  --pem \"path/to/cert.pem\" \\\n  --key \"path/to/key.key\" \\\n  --host localhost \\\n  --port \":3000\"\n```\n\n**Note:** see section below on generating an SSL certificate for `localhost` using the included shell script.\n\n## Installation\n\n### Build from source\n\n1. Install the Rust toolchain ([instructions](https://rustup.rs/))\n1. `git clone https://github.com/nixpig/joubini.git`\n1. `cd joubini`\n1. `cargo build --release`\n1. `mv ./target/release/joubini ~/.local/bin/`\n\n### Using TLS (SSL) on `localhost`\n\n1. Create a new CA and generate certificates using the included script: `bash -c scripts/ca.sh`\n1. Specify the `/tmp/localhost.crt` and `/tmp/localhost.key` when configuring `joubini`\n1. Trust certificate: `cp /tmp/localhost.crt /etc/ca-certificates/trust-source/anchors/ \u0026\u0026 update-ca-trust extract`\n1. In Chrome, add the `/tmp/myCA.pem` under `chrome://settings/certificates` -\u003e Authorities\n\n## Motivation\n\nI just wanted an interesting little project to work on in Rust which involves some basic networking stuff and that would actually be useful.\n\n## Alternatives\n\n- [Caddy](https://caddyserver.com/)\n- [NGINX](https://www.nginx.com/)\n- [Apache (httpd)](https://httpd.apache.org/)\n\n## Contribute\n\nAny suggestions, feel free to open an [issue](https://github.com/nixpig/joubini/issues).\n\n## Development\n\nIn order to bind to port 80 (or any port below 1024), you'll need to grant access to the binary to do so.\n\nReplace `$PATH_TO_PROJECT` in command below with the _absolute_ path to the project.\n\n```shell\nsudo setcap CAP_NET_BIND_SERVICE=+eip $PATH_TO_PROJECT/target/debug/joubini\n\n```\n\n## License\n\n[MIT](https://github.com/nixpig/joubini?tab=MIT-1-ov-file#readme)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnixpig%2Fjoubini","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnixpig%2Fjoubini","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnixpig%2Fjoubini/lists"}