Self-hosted service
Resinat/Resin avatar
Resinat/Resin

Resin: a self-hosted proxy pool gateway for large subscriptions

A high-performance proxy pool gateway. Turn massive proxy subscriptions into a stable, smart, and observable network with sticky sessions.

2,394 stars392 forksGoMIT

At a glance

What is it?
Resin aggregates many proxy subscriptions into one entrypoint with sticky sessions, health checks and a Web UI. It is a Go project with a Docker Compose quick start, and it is aimed at operators who already have more nodes than they can manage by hand.
Who is it for?
Adopt Resin if you already run a large, messy set of proxy subscriptions and want one stable entrypoint with sticky routing and a Web UI; skip it if you only have a handful of nodes, since a plain proxy client is less machinery.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 61 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Resin targets: many nodes, one stable outbound identity

Anyone running scrapers, marketplace accounts or regional API clients eventually accumulates proxy subscriptions from several providers. Each subscription has its own format, its own failure pattern, and its own latency profile, and the client code usually ends up knowing about all of them. Resin sits between the client and those subscriptions. The README describes it as a "high-performance intelligent proxy pool gateway" that aggregates distributed proxy resources into a unified proxy entrypoint with session stickiness.

The audience is narrow and specific: operators with large node counts. The project claims it can handle 100k+ proxy nodes, and the feature list is written for that scale, with cross-subscription deduplication, P2C plus domain-aware latency-weighted scoring, and Platform rules that carve independent pools out of one node set. If you have five proxies and one application, this is more moving parts than the problem deserves.

How the gateway routes: P2C scoring, circuit breaking and sticky leases

The mechanism described in the README has three layers. First, subscriptions are ingested in several formats: sing-box JSON, Clash JSON or YAML, URI lines (vmess, vless, trojan, ss, hysteria2, http, https, socks5, socks5h), plain IP:PORT lines, and Base64-wrapped text. Second, nodes are health-checked through passive and active checks plus outbound IP probing and latency analysis, and bad nodes are removed from selection. Third, selection uses P2C with domain-aware latency-weighted scoring, so the target domain influences which node wins.

The sticky part is the interesting design choice. Resin binds a business identity to an outbound IP rather than to a node. The README says that if a node fails, Resin switches to another node that shares the same IP. That distinction matters: stickiness survives node churn as long as some node with the same egress IP is still alive. Identity can be extracted from existing request headers, for example API keys, which the README calls zero-intrusion sticky access because clients often need no code changes.

State is not held only in memory. The README states that node health, latency statistics and lease bindings persist across restarts, and that subscription refresh is incremental so current connections are not interrupted. Whether that persistence survives a corrupt or deleted state volume is not documented, and the README does not describe a rollback path for a bad configuration change.

Installing Resin with Docker Compose and importing a first subscription

The README recommends Docker Compose as the quick-start path. The example below is the one it gives, with the admin and proxy tokens replaced by your own values. The image is ghcr.io/resinat/resin:latest, the default port is 2260, and the three volumes map cache, state and log directories.

yaml
services:
  resin:
    image: ghcr.io/resinat/resin:latest
    container_name: resin
    restart: unless-stopped
    environment:
      RESIN_ADMIN_TOKEN: "admin123"
      RESIN_PROXY_TOKEN: "my-token"
      RESIN_LISTEN_ADDRESS: 0.0.0.0
      RESIN_PORT: 2260
    ports:
      - "2260:2260"
    volumes:
      - ./data/cache:/var/cache/resin
      - ./data/state:/var/lib/resin
      - ./data/log:/var/log/resin

Start it with docker compose up -d. The README warns that custom endpoint ports must also be reachable from outside the container, and that Docker cannot add published ports to an already-running container, so a port range such as "2300-2399:2300-2399" has to be declared up front or host networking used instead.

bash
docker compose up -d

After the container is up, open http://127.0.0.1:2260 in a browser and log in with RESIN_ADMIN_TOKEN. In the left menu, open Subscriptions and add a node subscription, then wait briefly for the node pool to refresh. The .env.example file lists the same three settings for non-Compose runs: RESIN_ADMIN_TOKEN, RESIN_PROXY_TOKEN and RESIN_PORT, with a note that setting RESIN_PROXY_TOKEN to an empty value disables proxy authentication. Leaving it empty on a reachable host is a decision worth making deliberately.

Access modes and the endpoint model you have to plan around

Resin accepts traffic in three shapes: an HTTP forward proxy, a SOCKS5 forward proxy, and a URL-based reverse proxy. The README says inbound endpoints are added in the WebUI with hot reload, and that each listening port independently controls admin-console, HTTP forward, HTTP reverse and SOCKS5 access. That is flexible, but it pushes port planning to deployment time. Because Docker cannot publish ports on a running container, adding an endpoint later means recreating the container with the new port mapping, which is a real constraint rather than a UI detail.

The Node.js-free runtime image and the Go build are worth noting for operators who audit what they deploy. The Dockerfile builds the WebUI with node:22-alpine, then compiles the Go binary with CGO_ENABLED=0 and the build tags with_quic with_wireguard with_grpc with_utls, and ships it on alpine:3.21 running as an unprivileged resin user with three declared volumes. The file also carries a comment that the runtime stage must be kept in sync with .github/Dockerfile.release, and that GHCR release images are built from that other file, not this one. Two Dockerfiles that must stay in sync is a maintenance hazard the project itself flags.

Where Resin is the wrong tool, and what to use instead

The clearest limitation is scale mismatch. A single developer with a handful of proxies, or a team that needs one fixed egress, gets nothing from deduplication, Platform rules or P2C scoring, and takes on a stateful service with a database, a Web UI and persistent volumes. The go.mod shows modernc.org/sqlite and golang-migrate/migrate, so there is a schema that will need to survive upgrades.

A second limitation is format support. The README lists the accepted subscription formats and outbound node types explicitly. Anything outside that list, whether a proprietary provider format or a node type not named there, has no documented path in. If your provider emits something else, you convert it before Resin sees it.

A third is operational surface. Resin is a gateway with an admin console, tokens and listening ports. Exposing the admin console without a strong RESIN_ADMIN_TOKEN is a straightforward mistake, and the README's own example uses "admin123".

For a real alternative, sing-box is the closer comparison than a generic proxy client. Resin depends on github.com/sagernet/sing-box v1.12.21 and github.com/sagernet/sing v0.7.18, and it converts sing-box and Clash subscriptions into its own pool. Running sing-box directly means you configure outbounds and routing rules yourself and get no pool-level health scoring, no cross-subscription deduplication and no sticky lease bound to an egress IP. Resin is the layer you add when hand-maintained sing-box configuration stops scaling; sing-box is the layer you keep when it still does.

Licence, maintenance and upgrade cost

Resin is MIT licensed, and the repository is not archived. The last push was on 2026-08-01, and v1.2.0 was released the same day, with v1.1.2 on 2026-07-05 and v1.1.1 on 2026-05-16 before it. The release cadence over that window is steady, and the release pipeline badge in the README points at a GitHub Actions workflow, so tagged releases are produced by CI rather than by hand.

Upgrade cost depends on the state volume. The README states that node health, latency statistics and lease bindings persist across restarts, and the dependency list includes golang-migrate/migrate, which implies schema migrations run as part of the application. Backing up the directory mounted at /var/lib/resin before pulling a new image is the concrete precaution. The README does not document a downgrade procedure or a migration rollback, so treating an upgrade as one-way is the safer assumption. MIT terms place no conditions on internal use; if you redistribute Resin or a modified build, the licence text and copyright notice travel with it. That is a summary of the licence file, not legal advice.

Editorial conclusion

Adopt Resin if you already run a large, messy set of proxy subscriptions and want one stable entrypoint with sticky routing and a Web UI; skip it if you only have a handful of nodes, since a plain proxy client is less machinery. Before trusting it, verify that your subscription formats appear in the supported list, that RESIN_PROXY_TOKEN is set to something other than the example value, and that any custom endpoint ports are pre-published in docker-compose.yml, because Docker cannot add published ports to a running container.

Frequently asked questions

How do I install Resin?

The README recommends Docker Compose: define the ghcr.io/resinat/resin:latest image with RESIN_ADMIN_TOKEN, RESIN_PROXY_TOKEN, RESIN_LISTEN_ADDRESS and RESIN_PORT set, map port 2260, mount the cache, state and log volumes, then run docker compose up -d. The repository also ships a Dockerfile and a docker-compose.yml.example for other deployment paths.

What proxy and subscription formats does Resin accept?

The README lists sing-box JSON, Clash JSON or YAML, URI line formats such as vmess, vless, trojan, ss, hysteria2, http, https, socks5 and socks5h, plain IP:PORT lines, and Base64-wrapped text subscriptions. Outbound node types include socks, http, shadowsocks, vmess, trojan, wireguard, hysteria, vless, shadowtls, tuic, hysteria2, anytls and ssh.

How does Resin keep the same outbound IP for a business account?

Resin binds a business identity to an outbound IP rather than to a specific node. The README states that if a node fails, Resin switches to another node with the same IP, and that identity can be extracted from existing request headers such as API keys so clients often need no code changes.

Do I need to publish extra ports for custom Resin endpoints?

Yes. The README notes that custom endpoint ports must be reachable from outside the container and that Docker cannot add published ports to an already-running container, so you pre-publish the range in the ports section or use host networking.

Does Resin keep node health and session state across restarts?

The README states that node health, latency statistics and lease bindings persist across restarts, and the deployment examples mount a state volume at /var/lib/resin for that purpose. The README does not document a downgrade or migration rollback path.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. Resinat/Resin on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/resinat-resin.svg)](https://hysenlabs.com/projects/resinat-resin)