{"id":42991350,"url":"https://github.com/Xetera/localproxy","last_synced_at":"2026-02-10T22:00:37.241Z","repository":{"id":334693989,"uuid":"1142037063","full_name":"Xetera/localproxy","owner":"Xetera","description":"✨ Magically access any process/container on your computer through a .localhost URL","archived":false,"fork":false,"pushed_at":"2026-02-02T22:41:42.000Z","size":401,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-03T11:42:11.887Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Xetera.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-25T21:10:36.000Z","updated_at":"2026-02-02T22:41:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Xetera/localproxy","commit_stats":null,"previous_names":["xetera/localproxy"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Xetera/localproxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xetera%2Flocalproxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xetera%2Flocalproxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xetera%2Flocalproxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xetera%2Flocalproxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Xetera","download_url":"https://codeload.github.com/Xetera/localproxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xetera%2Flocalproxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29319236,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T20:44:44.282Z","status":"ssl_error","status_checked_at":"2026-02-10T20:44:43.393Z","response_time":65,"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":[],"created_at":"2026-01-31T03:00:31.196Z","updated_at":"2026-02-10T22:00:37.230Z","avatar_url":"https://github.com/Xetera.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Localproxy\n\n[![Build](https://github.com/Xetera/localproxy/actions/workflows/build.yml/badge.svg)](https://github.com/Xetera/localproxy/actions/workflows/build.yml)\n\n```sh\ncd ~/projects/coolproject\nPORT=$(random) npm run dev\ncurl https://coolproject.localhost\n# ✨ it just works like magic\n```\n\n![](./showcase.jpg)\n\nI hate having to remember random port numbers. Localproxy solves this problem for me. It runs an embedded caddy server on port 80 and 443 with a self-signed certificate, and auto-discovers targets from both docker using `EXPOSE` fields and [labels](#docker-example-with-labels), and local processes listening to ports running directly under a given \"projects\" folder.\n\nLocalproxy supports proxying http(s), http/2, http/3 (QUIC) and TCP connections. If there's more than one service running on the same port (ex: 2 postgres databases listening on port 5432), the TCP connections MUST use TLS to allow the proxy to determine the target domain. Otherwise that information is missing without a layer 7 protocol involved (ex: redis with `--tls --sni` and postgres with `?sslnegotiation=direct\u0026sslmode=require`)\n\nCertain well-known ports on your computer are also checked to detect software you may have running locally outside your regular \"projects\" folder like syncthing, to also proxy connections there as well.\n\n---\n\nSadly, the project requires root privileges on macos because:\n\n1. Unlike Linux, On MacOS, docker runs on top of a Linux VM. Which makes reaching into docker ports impossible without having root access. There's really no good workaround for this that I know of.\n2. MacOS for whatever reason does not automatically map `*.localhost` to 127.0.0.1. To allow this mapping, localproxy reaches into `/etc/hosts` to add entries just because it's the simplest alternative since we already need root.\n3. [There's a bug that prevents listening to privileged ports on specific interfaces without root](https://news.ycombinator.com/item?id=18302380). That's right, you can listen to port 80 on `0.0.0.0` but not `127.0.0.1`.\n\nIf you don't need docker integration in macos, you can run without root after doing a small setup to allow resolving localhost and internal tlds.\n\n```\nbrew install dnsmasq\necho 'address=/.localhost/127.0.0.1' \u003e\u003e $(brew --prefix)/etc/dnsmasq.conf\necho 'address=/.internal/127.0.0.1' \u003e\u003e $(brew --prefix)/etc/dnsmasq.conf\nsudo brew services start dnsmasq\n```\n\n```sh\nsudo CGO_ENABLED=0 go run ./cmd/localproxyd --watch ~/myprojects\n```\n\nThen navigate to the dashboard https://localhost\n\n#### Flags\n\n- `--watch` Adds a folder to watch for processes. Local process watching is disabled if no folders are watched.\n- `--https-redirect` Force https redirects for all created endpoints (default: false)\n- `--log-level` Log level for the caddy server. `error`, `info`, `debug` (default: info)\n- `--trace-process-logs` Show logs from external processes on the dashboard using dtrace on macOS. Requires disabling SIP. This WILL eventually lock up your system badly enough for you to hold down the power button for a restart [unless you're on Tahoe](https://news.ycombinator.com/item?id=45974681) (default: false)\n\n### Local process example\n\n```sh\ncd ~/myprojects/project1\n# run a webserver on any port\nnpm run dev\n# localproxy uses the path passed to --watch to\n# automatically detect processes running in its sub-folders\ncurl https://project1.localhost\n```\n\n### Docker example with labels\n\nProxying traffic to docker containers works without exposing ports using `-p`. Instead you can use the following labels to configure the proxy behavior:\n\n- `localproxy.subdomain` controls the [subdomain].internal domain\n- `localproxy.port` 443/80 -\u003e $port (used for webservers)\n- `localproxy.tcpport` $tcpport -\u003e $tcpport (used for for tcp servers that listen non non-web ports)\n\nTo allow reaching out to localproxy urls _from within_ containers, you need to use and map the alternative `.internal` tld to `host-gateway` using `--add-hosts`. `.localhost` specifically only points to 127.0.0.1 as per its RFC, which creates problems\n\n##### Using docker run\n\n```sh\ndocker run --add-host=test.internal:host-gateway alpine/curl https://test.internal\n```\n\n##### Using docker-compose\n\n```yaml\nservices:\n  curl:\n    image: alpine/curl\n    command: curl https://test.internal\n    extra_hosts:\n      - test.internal:host-gateway\n```\n\n#### Postgres\n\n```sh\ndocker run --name postgres -l localproxy.tcpport=5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres\n```\n\nTwo requirements for connection:\n\n1. `sslmode` has to be `require` to not attempt a plaintext connection\n2. `sslnegotiation` has to be `direct` to use TLS instead of STARTTLS\n\n```sh\npsql \"postgresql://postgres@postgres.localhost/postgres?sslmode=require\u0026sslnegotiation=direct\"\n```\n\n#### Redis\n\n```sh\ndocker run --name myredis -l localproxy.tcpport=6379 redis\n```\n\nConnect to it from the host without exposing ports. Sadly redis-cli doesn't seem to use the local trust chain on macos. You may be able to omit `--insecure` on other platforms.\n\n```sh\nredis-cli --tls --insecure -h myredis.localhost --sni myredis.localhost\n# If you want to explicitly verify the certificate\nredis-cli --tls --cacert \"$(mkcert -CAROOT)/rootCA.pem\" -h myredis.localhost --sni myredis.localhost\n```\n\n### Logs\n\nBy default localproxy tries to capture stdout logs from local processes as well as docker containers. However on macos this requires you to partially turn off SIP in recovery mode with\n\n```sh\ncsrutil enable --without dtrace\n```\n\nIf you're a yabai user, you'll want to combine this with the flags yabai requires. [Relevant documentation.](https://github.com/asmvik/yabai/wiki/Disabling-System-Integrity-Protection)\n\n```sh\ncsrutil enable --without dtrace --without fs --without debug --without nvram\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FXetera%2Flocalproxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FXetera%2Flocalproxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FXetera%2Flocalproxy/lists"}