FreeSocks Control Plane
FreeSocks gives free proxy access to people in countries where the Internet is heavily censored. This repository is the software that runs the service: the website, accounts, key handout, payments and the admin console. The proxy servers themselves live elsewhere; this app creates and manages the keys people use to connect to them.
Anyone can run their own copy. It is built to be self-hosted from start to finish, with no outside services required.
What people can do
- Get an account without giving anything away. No email, phone number or password. A
- Get a connection key. One click creates a key that works with common proxy apps. The
- Choose how they connect. Pick a server location, or let the service choose the least
- Fix things themselves. Replace a key, move to another server, change their account
- Check the network. A public status page shows which locations are up, how busy they
- Support the service. Buy a membership (Bitcoin, other cryptocurrencies, card or
The site is available in English, Persian, Arabic, Russian and Chinese.
What operators can do
Operators manage everything from an admin console that only accepts passkeys. From there they can:
- add proxy servers and choose which ones new keys go to, and (once switched on) set up a
- put a node behind replaceable edges and approve it before members get it
- set up plans (free, member, and any others) and what each one allows
- look up and help users by their support ID, which is safe to share
- create membership codes, configure payments, and see revenue
- edit the status page, recommended apps, site banner, theme and rate limits
- set up storage mirrors, so people can still fetch their keys if the main site is blocked
- read user problem reports and a full audit log
- create API tokens with limited permissions for automation
How it protects people
- No stored IP addresses. The app, the web server and the puzzle service are all set up
- No personal details. Accounts have no name, email or phone. Account numbers are stored
- Nothing loaded from other sites. Fonts, scripts and the puzzle all come from the same
- Protection from the middle. When turned on, the browser encrypts its requests so that
- Replaceable entry points. Servers can sit behind front addresses that FCP creates,
- Idle accounts are paused, not deleted. A free key that hasn't been used for a while is
How it works
Website: browser ──► web server (Caddy) ──► Convex backend ──► database
│
└── serves the website files
Connecting: proxy app ──► edge (optional) ──► proxy server
- Backend: Convex, self-hosted in Docker. It holds the database,
convex/.
- Website: a Svelte app built into plain static files (
src/client/).
/api requests to the backend.
- Proxy servers: FCP talks to proxy software through a common interface. Two are
- Puzzle: Cap, a self-hosted proof-of-work check, stops bots
Run it locally
You need Bun (the version is pinned in package.json) and Docker with
Compose v2. Use Bun only; bun.lock is the only lockfile.
# 1. Start the backend in Docker
cp .env.docker.example .env.docker
bun install
bun run selfhost:up # backend + its dashboard
bun run selfhost:env # writes .env.local so the CLI can reach the backend
2. Give the backend its settings (once)
for k in SESSION_SIGNING_KEY ADMIN_SESSION_SIGNING_KEY ADMIN_BOOTSTRAP_SECRET IP_HASH_SALT ACCOUNT_ID_PEPPER; do
bunx convex env set "$k" "$(openssl rand -hex 32)"
done
bunx convex env set ENVIRONMENT development
bunx convex env set CAP_DEV_BYPASS true # skip the puzzle in local dev
bunx convex env set WEBAUTHN_RP_ID localhost
bunx convex env set WEBAUTHN_ORIGIN http://localhost:5173
3. Run the backend code and the website (reloads on change)
bun run dev
4. In another terminal, load the default plans and settings (safe to repeat)
bunx convex run seed:seedCutover '{}'
Open the website at http://localhost:5173 and the Convex dashboard at http://localhost:6791.
To create the first admin, go to /admin and enter your ADMIN_BOOTSTRAP_SECRET
(bunx convex env get ADMIN_BOOTSTRAP_SECRET).
If the website says it can't reach the server, the Docker backend has stopped: run
bun run selfhost:up again. To start over with an empty database, run
docker compose --env-file .env.docker down -v.
Run it in production
Production runs as a single Docker Compose stack (docker-compose.stack.yml):
Postgres, the Convex backend, Caddy (HTTPS and the website), the Cap puzzle service, backups,
and a one-time job that deploys the code and loads the defaults. To set it up:
- Create the two settings files and fill in every secret that can be generated:
cp .env.beta.example .env.beta
cp .env.convex.example .env.convex
bun run bootstrap
- Fill in the rest by hand. In
.env.beta: your domain, an email for HTTPS certificates,
BACKUP_S3_*, plus BACKUP_AGE_PUBLIC_KEY to encrypt the
backups). Accounts are anonymous and can't be rebuilt after a disk loss, so the backup
service refuses to run without offsite storage unless you set
BACKUP_ALLOW_LOCAL_ONLY=true on a throwaway server. In .env.convex: your passkey
domain (WEBAUTHN_*) and any payment keys.
- Start the puzzle service and the web server, then create the puzzle keys. Open
https://your-domain/cap, sign in with the CAP_ADMIN_KEY that bootstrap printed,
create a site key, and copy its key and secret into CAP_SITE_KEY and CAP_SECRET in
.env.convex. The deploy step refuses to run until these are set.
docker compose -f docker-compose.stack.yml --env-file .env.beta up -d --build web cap
- Start everything. This deploys the code and loads the defaults:
docker compose -f docker-compose.stack.yml --env-file .env.beta up -d --build
Then open /admin, register your passkey, and add a proxy server. The full guide, including
updates, backups and rollback, is beta-deploy.md. Every setting and
secret is explained in secrets.md and
convex-self-hosting.md.
Checks
Every change must pass these. CI runs the same ones.
bun run test # unit and backend tests, no running server needed
bun run typecheck
bun run convex:bundle-check # the backend code will bundle the way a deploy does
bun run lint # bun run format fixes formatting
bun run build
tsc uses TypeScript 7's side-by-side setup.
Svelte's checker still needs the TypeScript 6 compiler
API, supplied by Microsoft's @typescript/typescript6 compatibility package
under the typescript alias. @typescript/native supplies the TypeScript 7 CLI;
keep both aliases when updating the compiler.
Larger suites run in Docker against throwaway servers:
bun run test:integration:remnawave # FCP against a real Remnawave panel
bun run test:integration:remnawave-node # FCP against a real panel and a real node
bun run test:compat # real proxy apps import and use FCP's keys
bun run test:integration:edge-connection # a member connects through an L4 and an L7 edge
See client-compatibility.md for what the compat suite proves;
the edge-connection suite is the release gate for edges (docs/edges.md "Supported matrix").
Where things are
| Path | What's there |
| ----------------------- | ------------------------------------------------------------------------------ |
| convex/ | The whole backend: data model, API routes, scheduled jobs |
| convex/lib/ | Shared backend helpers, proxy-server adapters, payment adapters |
| src/client/ | The website, including the admin console under routes/admin/ |
| src/shared/contracts/ | The shape of every API response, shared by both sides |
| messages/ | Translations, one file per language |
| docker/, Caddyfile | Images and web server config for the production stack |
| scripts/ | Setup, key generation and test runners |
| tests/compat/ | The client compatibility suite |
| verifier-extension/ | Early browser extension that checks the website hasn't been changed in transit |
Documentation
| Read this | To learn about | | ----------------------------------------------------------------- | ----------------------------------------------------- | | project-inventory.md | Every feature, what's finished, and what's left | | beta-deploy.md | Running the full stack on a server | | convex-self-hosting.md | The backend, its settings, and the web server setup | | secrets.md | Every secret: who creates it and how to change it | | backends.md | How FCP talks to proxy servers, and adding a new one | | outline-setup.md | Adding an Outline server | | servers.md | Managing a proxy server, and deploying a fronted node | | edges.md | Replaceable front addresses for proxy servers | | billing.md | Memberships, payments, donations and referrals | | btcpay-server-runbook.md | Running the BTCPay server for Bitcoin payments | | privacy.md | What is never stored, and how to keep it that way | | account-number-design.md | How account-number sign-in works | | threat-model-cdn-blinding.md | Encryption between the browser and the backend | | oob-verification.md | Checking the website you got is the one we built | | client-compatibility.md | Testing real proxy apps against FCP |
Contributing
Code, docs, translations, and testing from inside censored networks all help. Start with CONTRIBUTING.md.
Security
Report security problems privately, as described in SECURITY.md. Please don't open a public issue: people in high-risk places depend on this software.
License
AGPL-3.0-or-later. If you run a modified version that people use over a network, public or private, you must offer them its source code.