Public release 1.0.0 · isolated workers · permanent location ports
Independent project. xTor is an unofficial third-party client manager. It is not affiliated with, sponsored by, endorsed by, or approved by The Tor Project. “Tor” and related marks belong to The Tor Project.
Release integrity. Use only versioned release assets published for
1.0.0, and verify the matching SHA-256 checksum before installation. A file name or version label alone does not establish that an archive is an official xTor release asset.
Run the public installer on a native Debian or Ubuntu server with systemd:
curl -fsSL https://raw.githubusercontent.com/IzumiRain/xTor/main/bootstrap.sh | sudo shThe bootstrap pins release 1.0.0, downloads its offline bundle and published
checksum from the matching GitHub release, verifies the archive, and starts the
normal installer. The installer checks the host and installs only missing,
allow-listed dependencies through the server's configured Debian/Ubuntu
repositories.
To review the bootstrap before running it:
curl -fsSLo xtor-bootstrap.sh https://raw.githubusercontent.com/IzumiRain/xTor/main/bootstrap.sh
less xtor-bootstrap.sh
sudo sh xtor-bootstrap.shInstaller options can be forwarded after -s --:
curl -fsSL https://raw.githubusercontent.com/IzumiRain/xTor/main/bootstrap.sh \
| sudo sh -s -- --skip-catalog-refreshThe normal first installation also attempts one bounded nodes and locations refresh. If that network request fails, the local installation remains complete and reports how to retry it later.
xTor runs multiple isolated Tor client workers on one server. Each started location receives a loopback-only SOCKS5 endpoint, so an application chooses its preferred exit country by choosing that location's port.
Application A ── socks5h://127.0.0.1:<DE-port> ── DE worker ── Tor network ── preferred DE exit
Application B ── socks5h://127.0.0.1:<NL-port> ── NL worker ── Tor network ── preferred NL exit
The requested country is a Tor exit preference, not a guarantee. xTor checks Tor readiness, hostname-based remote DNS, HTTPS connectivity, and the observed exit country before reporting a healthy route. Tor circuits, relay availability, and GeoIP results can still change over time.
xTor does not create a public proxy, web panel, HTTP API, VPN, relay, bridge, or
exit node. Managed SOCKS listeners stay on 127.0.0.1 for trusted local
applications on the server.
flowchart LR
A[Applications] -->|SOCKS5H| D1[DE permanent port]
A -->|SOCKS5H| D2[NL permanent port]
D1 --> W1[Isolated DE Tor client]
D2 --> W2[Isolated NL Tor client]
W1 --> T1[Tor network] --> E1[Preferred DE exit]
W2 --> T2[Tor network] --> E2[Preferred NL exit]
Four different states are involved. Keeping them separate prevents most configuration mistakes:
| Concept | Scope | What it means |
|---|---|---|
| Catalogue availability | Global | Whether current exit data says a country has eligible HTTPS exits. |
| Profile membership | Per profile | Whether a location belongs to that named group. It does not itself mean the worker is running. |
| Runtime state | Active profile | Whether that location's isolated Tor worker is started and verified. |
| Permanent port | Global | The stable SOCKS port reserved for a country across every profile, even while stopped or unselected. |
After installation, either command opens the menu:
sudo xtor
# or
sudo xtA pristine installation has an active Default profile. Use it for the first route:
- Open Location Manager.
- Choose a location by its visible number. If Germany is
[16], enter16in the TUI—notDE. - Press [a] Add to Profile, then [s] Start. Starting an unselected row can also offer to add it to the active profile before starting it.
- Read the location's permanent SOCKS port from the table.
- Configure a local application for
socks5h://127.0.0.1:<location-port>. - Use [t] Test, [f] Force Start, View Logs, or Watchdogs when diagnosing a route.
Use socks5h or an equivalent remote-DNS mode. The h makes the application
send hostnames through the proxy instead of resolving them with ordinary local
DNS.
TUI numbers belong only to the current displayed catalogue snapshot. The CLI
uses stable country codes such as DE, and the permanent port remains the
endpoint identity on that installation.
A profile is a saved group of locations—similar to a separate room with its own set of Tor workers. Examples might be:
Profile: de-fr
DE Germany
FR France
Profile: gaming
NL Netherlands
Profile: friends
DE Germany
NL Netherlands
RU Russia
US United States
Exactly one profile is active at a time. Profile membership is independent: DE can belong to one profile, several profiles, or none. Its port is not copied per profile; the same DE port is used everywhere on that installation.
When another prepared profile is activated, xTor:
- validates the target profile and its current catalogue availability;
- stops the old profile's workers;
- provisions, starts, and verifies every location in the target profile;
- commits the new active profile only after all required work succeeds.
If activation fails, xTor attempts to stop the incomplete target and restore the previous profile and runtime state. Switching profiles interrupts existing application streams; TCP connections cannot move between Tor workers.
| Action | Behavior |
|---|---|
| Create | Creates a named, inactive, empty profile. |
| Rename | Changes the display name without changing worker IDs, locations, or ports. |
| Activate | Transactionally stops the old profile and starts/verifies every target location. Empty profiles cannot be activated. |
| Remove | Removes an inactive profile and its worker configuration. The active profile must be switched first. Global location-port reservations remain. |
Location Manager edits only the currently active profile. To prepare a new inactive profile before activating it, use the CLI:
sudo xtor profile create de-fr
sudo xtor location add DE --profile de-fr
sudo xtor location add FR --profile de-fr
sudo xtor profile activate de-frAfter activation, Location Manager can add or remove locations from that profile with numeric row selections.
Location Manager is the operational view of xTor's global location catalogue. It shows:
AUTOand every country in the current validated catalogue;- saved profile locations that disappeared from the latest catalogue, marked
UNAVAILABLE; - active-profile membership and worker state;
- availability status; and
- each displayed location's reserved SOCKS port.
The table may be longer than the terminal. Use Up/Down, Page Up/Page Down, Home/End, or [n/p] Scroll while the command helper remains available below the table.
| Command | Behavior |
|---|---|
| [s] Start | Starts and verifies the selected location once. If it is unselected, xTor can add it to the active profile after confirmation. |
| [f] Force Start | Repeats clean start-and-verify attempts for a specific requested country. |
| [x] Stop | Stops the selected active-profile worker and disables its running intent. Membership and port remain. |
| [r] Restart | Rebuilds the selected route and verifies it again. Existing streams are interrupted. |
| [t] Test | Checks the current Tor route, remote DNS, HTTPS reachability, and observed country. |
| [u] Update List | Runs the same atomic nodes-and-locations refresh as Home's Update Nodes action. |
| [a] Add to Profile | Adds the selected available location to the active profile. |
| [d] Remove from Profile | Stops/removes that active-profile worker configuration, but keeps the global permanent port reservation. |
The row number is only a presentation selector. It can change when the catalogue changes; it is never stored as a profile, worker, country, or port identity.
Location Manager is not the complete historical port registry. If a country is absent from the current catalogue and from every profile, its preserved reservation remains visible in Port Manager.
xTor maintains one global, append-only location-port registry:
AUTOis fixed at127.0.0.1:64000.- On a fresh installation, newly discovered country codes are sorted and
assigned sequential unused ports beginning at
64001. - A country discovered later receives a new unused port.
- Existing country ports are never automatically renumbered.
- Stop/start, profile changes, catalogue refreshes, availability changes, software update, and rollback do not move current assignments.
- Removing a location from every profile or seeing it disappear from the catalogue does not release its port.
- A country uses the same global port in every profile.
This means an application configured for the DE endpoint cannot silently reach a newly discovered country after a refresh.
Port Manager displays every permanent reservation, including retained
unavailable locations. An operator may deliberately move a country to an unused
port between 64001 and 65535:
sudo xtor port set DE 64555AUTO cannot be changed. A successful change updates every profile containing
that country and transactionally regenerates affected workers. Active affected
workers are restarted and verified. If that fails, xTor attempts to restore the
old configuration and runtime.
The previous port is permanently retired and cannot be assigned to another
country or reused manually. This prevents stale application settings from being
silently redirected. Port history depends on xTor state: a full uninstall that
deletes /var/lib/xtor intentionally deletes the registry; use --keep-state
when that history must survive uninstall.
This feature updates xTor's knowledge of usable Tor exits and derives an updated location list from the same verified data. It is intentionally one atomic operation, so the node view, location view, availability counts, and permanent port registry cannot drift apart.
There are two TUI entry points:
- Home: [5] Update Nodes
- Location Manager: [u] Update List
Both call the same CLI operation:
sudo xtor catalog refreshxTor fetches a bounded snapshot from the fixed HTTPS Onionoo source containing currently running relays with the Exit flag. For each usable record it processes the relay fingerprint, country, flags, exit-policy summary, and reported exit addresses.
Before accepting the response, xTor checks its source behavior, size, JSON
shape, supported Onionoo schema, publication timestamp, completeness, relay
identities, country codes, addresses, and exit policies. A running relay counts
as an eligible HTTPS exit only when it is also Valid and Exit, is not marked
BadExit, and its policy permits TCP port 443.
This is an xTor catalogue update. It does not upgrade the Tor package, edit
the host's /etc/tor/torrc, force Tor to use a downloaded fingerprint list, or
replace Tor's own directory consensus. Tor remains authoritative when it builds
circuits.
xTor groups the accepted exit records by two-letter country code and rebuilds the visible location catalogue. It recalculates each country's running-exit count, eligible-HTTPS-exit count, and availability status.
Therefore the location list is dynamic rather than a permanently hard-coded country menu:
- a country with newly observed exits can appear;
- a country can move between
AVAILABLE,CONSTRAINED,FRAGILE, andUNAVAILABLEas eligible capacity changes; - a country that disappears from the new snapshot stops being currently available; and
- saved or historically registered locations retain their identity and port even when unavailable.
The location list is derived from the node snapshot. xTor does not download a second country list from an unrelated API, and no API token is required.
| Updated by a successful refresh | Preserved by every refresh |
|---|---|
| Cached relay fingerprints, flags, exit policies, and reported exit addresses | Existing location-port assignments |
| Country list derived from the accepted snapshot | Retired ports; they are never reused |
| Running and eligible HTTPS exit counts | Membership of every profile |
| Location availability states | Active profile and worker running intent |
| New permanent reservations for newly discovered country codes | Host Tor package and /etc/tor/torrc |
| Catalogue timestamps and health metadata | Running workers; refresh does not start, stop, or restart routes |
New location ports are committed before the new catalogue becomes visible. If registry reconciliation cannot complete safely, xTor does not publish the new location list.
A normal pristine install attempts one refresh after local installation checks pass. The installed catalogue timer later polls on an hourly schedule with jitter and performs a network refresh only when the cached source data is due. The source's cache lifetime is respected, with a bounded fallback and failure backoff.
If the source is unavailable or a response fails validation:
- the last valid catalogue remains in use;
- its health becomes
STALEorREJECTEDas appropriate; - existing profiles, ports, and running routes are not rewritten; and
- the operation reports a friendly retry path.
If no valid cache exists yet, country selection remains unavailable until a refresh succeeds. Retry manually with:
sudo xtor catalog refreshAn unchanged upstream response is reported as current without replacing the valid cache.
Availability describes eligible HTTPS exit capacity in the latest valid xTor catalogue. It is not a guarantee that a new circuit will start or remain in that country.
| Location status | TUI color | Meaning |
|---|---|---|
SPECIAL |
Tor purple | The virtual AUTO location; not a country-capacity rating. |
AVAILABLE |
Green | At least 10 eligible HTTPS exits are listed. |
CONSTRAINED |
Amber | 3–9 eligible HTTPS exits are listed; fewer choices are available. |
FRAGILE |
Red | 1–2 eligible HTTPS exits are listed; startup and continuity are more likely to fail. |
UNAVAILABLE |
Gray | No eligible HTTPS exit is listed, or a retained country disappeared from the current catalogue. |
The TUI always shows the text label as well as color. Catalogue health is a separate status:
| Catalogue state | Meaning |
|---|---|
AVAILABLE |
An internally integrity-checked cache exists and is current. |
STALE |
The last valid cache remains usable but is overdue, or the latest fetch failed. |
REJECTED |
The newest response failed validation; the previous valid cache remains in use. |
UNAVAILABLE |
No valid cache exists, so catalogue countries cannot be selected. |
Normal Start verifies a requested route once. Force Start performs repeated clean start-and-verify attempts when the observed exit country is wrong or a known retryable route failure occurs:
sudo xtor force-start DE
sudo xtor force-start DE --attempts 10 --retry-delay 3Force Start accepts 1-20 attempts and a 0-60 second retry delay. It requires
a specific country already in the active profile; AUTO is not accepted.
Success is reported only after Tor readiness, remote DNS, HTTPS, and observed
country verification pass.
Exhaustion, cancellation, or a terminal failure leaves the worker stopped and disables its running intent, so an unverified country is not left behind a labelled port. Force Start improves the opportunity to obtain the requested preference; it cannot guarantee it.
The menu is bounded to the current terminal viewport and supports wide,
standard, phone-sized, ASCII, TERM=dumb, and NO_COLOR terminals. Long lists
support keyboard and displayed shortcut navigation. Long-running operations
show loading feedback, while result pages provide friendly explanations and
retain sanitized technical support codes.
| TUI screen | What it provides |
|---|---|
| Home | Active profile, active/available locations, exit counts, catalogue age, CPU/RAM, autostart, lifecycle actions, and diagnostics. |
| Profile Manager | List, create, rename, activate, and remove profiles. |
| Location Manager | Every current catalogue location, saved unavailable locations, runtime controls, Force Start, test, refresh, and active-profile membership. |
| Speed & Ping Test | Bounded point-in-time latency, throughput, and HTTPS results for active-profile locations. |
| Port Manager | Every permanent location port and intentional port reassignment. |
| View Logs | A bounded, redacted view covering the entire xTor project. |
| Watchdogs | Project-wide worker intent, health, recovery, strikes, and cooldown. |
| Catalogue Details | Cache health, source publication time, counts, and refresh metadata. |
| Doctor | Human-readable host, Tor, permissions, ports, ownership, and project checks. |
The CLI uses stable country codes instead of TUI row numbers:
xtor profile list
xtor profile create NAME
xtor profile rename PROFILE NAME
xtor profile activate PROFILE
xtor profile remove PROFILE
xtor location available
xtor location list [--profile PROFILE]
xtor location add CODE [--profile PROFILE]
xtor location remove CODE [--profile PROFILE]
xtor port list
xtor port set CODE PORT
xtor catalog status
xtor catalog refresh [--if-due]
xtor auto select [--profile PROFILE] [--max-candidates 2..10]
xtor start [CODE]
xtor force-start CODE [--attempts 1..20] [--retry-delay 0..60]
xtor stop [CODE]
xtor restart [CODE]
xtor test CODE
xtor speedtest CODE
xtor status
xtor logs [CODE] [-n LINES]
xtor watchdog --status
xtor watchdog [CODE] --once
xtor doctor
xtor autostart enable|disable|status
xtor version
Structured CLI actions print JSON by default for scripts and automation. The TUI converts the same results and failures into human-readable screens.
- Native Debian or Ubuntu Linux.
- systemd running as PID 1.
- Root access or a sudo-capable operator.
curlfor the displayed one-line bootstrap.- Outbound access to the host's configured package repositories when a required package is missing, plus Tor and the catalogue source during normal use.
The bundle installer verifies these runtime requirements before changing any xTor-owned path:
python3 xTor runtime
tor + tor-instance-create isolated Tor worker creation
tor-geoipdb Tor country/GeoIP data
systemd service and timer lifecycle
iproute2 ss listener checks
passwd account/group cleanup helpers
libc-bin getent account lookup
ca-certificates HTTPS certificate trust
Already-satisfied packages are not reinstalled. Packages installed through
apt remain host-managed; xTor update, rollback, and uninstall never remove or
downgrade them.
For a downloaded release asset, verify the published checksum before extraction:
sha256sum -c SHA256SUMS
mkdir -p /root/xtor-1.0.0
tar -xzf xtor-offline-1.0.0.tar.gz -C /root/xtor-1.0.0
cd /root/xtor-1.0.0
sudo ./install.shUseful installer options:
sudo ./install.sh --skip-catalog-refresh
sudo ./install.sh --skip-dependency-install
sudo ./install.sh --no-enable-timer
sudo ./install.sh --no-color
sudo ./install.sh --json--skip-dependency-install is verification-only: it never invokes apt and
fails before xTor-owned mutation if a required component is absent. The bundle
contains xTor and its systemd units; it does not vendor Debian packages or add
package repositories.
AUTO ranks a bounded set of eligible countries using current catalogue
capacity, then measures real Tor routes sequentially. A candidate must pass Tor,
remote DNS, HTTPS, and country verification. The score uses 40% HTTPS first-byte
latency and 60% throughput for that point-in-time candidate set.
Speed results are measurements, not promises. Tor circuits, relay load, the destination, and the server's network can change immediately afterward.
Home displays point-in-time host CPU usage and used/total RAM. These values are operational indicators, not a capacity benchmark.
Each active location runs a full Tor client. Historical five-minute samples on a 2-vCPU, 3.759-GiB server with no application traffic observed were:
| Per active location | Historical observation |
|---|---|
| Tor resident memory (RSS) | approximately 84.22-84.45 MiB |
| Average Tor-process CPU | approximately 0.44-0.75% of one logical CPU |
| Highest five-second CPU sample | approximately 4.90-6.34% of one logical CPU |
For initial planning, reserve about 100 MiB RAM per active location, then keep separate headroom for the operating system, catalogue cache, xTor operations, and local applications. Bootstrap, directory downloads, circuit construction, retries, Force Start, watchdog recovery, and real traffic can use more. Test the intended workload on the intended server.
xTor does not silently discover or install software releases. Obtain the intended bundle from a trusted release, verify its checksum, extract it into a new directory, and run that target bundle's updater:
BUNDLE=/absolute/path/xtor-offline-1.0.0.tar.gz
UPDATE_DIR=$(mktemp -d /tmp/xtor-update.XXXXXX)
tar -xzf "$BUNDLE" -C "$UPDATE_DIR"
cd "$UPDATE_DIR"
sudo ./update-local.sh "$BUNDLE" --dry-run
sudo ./update-local.sh "$BUNDLE" --confirm 'UPDATE XTOR TO 1.0.0'Rollback and uninstall are explicit:
sudo /opt/xtor/rollback.sh --dry-run
sudo /opt/xtor/rollback.sh --confirm 'ROLLBACK XTOR TO VERSION'
sudo /opt/xtor/uninstall.sh --dry-run
sudo /opt/xtor/uninstall.sh --confirm 'UNINSTALL XTOR'Use --keep-state when /var/lib/xtor and its location-port history must be
retained. Uninstall preserves Debian's Tor package, /etc/tor/torrc, unrelated
services, and host-managed packages.
xTor is a local operator tool, not a public proxy service. Before installation, read SECURITY.md, obtain any required permission from the hosting provider, and review current provider terms, Tor restrictions, destination terms, local law, resource limits, and abuse procedures.
Do not use xTor for a public/LAN SOCKS gateway, torrent/P2P traffic, mass circuit rotation, relay/bridge/exit operation, abuse, or claims of guaranteed anonymity, country, IP address, speed, uptime, or capacity. Verify that every application actually uses hostname-based SOCKS and does not bypass the proxy through DNS, UDP, IPv6, telemetry, updates, or fallback connections.
Never publish credentials, private keys, Tor control cookies, private destinations, or unsanitized logs and screenshots.
| Capability | xTor's approach |
|---|---|
| Multiple explicit exit preferences | One isolated Tor client per started location. |
| Profiles | One active named profile with independent membership and transactional switching. |
| Dynamic location discovery | Locations are derived from a validated current exit snapshot instead of a permanently hard-coded country menu. |
| Safe node/location refresh | Nodes, derived locations, availability, and new port reservations are reconciled as one atomic operation. |
| Endpoint stability | Global append-only location-port registry; existing ports do not move during refreshes. |
| Wrong-exit recovery | Bounded Force Start with full verification and fail-closed exhaustion. |
| Correctness checks | Tor readiness, remote DNS, HTTPS, and observed-country checks before healthy status. |
| Operations | Project-wide logs/watchdogs, Doctor, catalogue health, update, rollback, and ownership-aware uninstall. |
| Access surface | Loopback-only SOCKS and private control sockets; no web panel or HTTP management API. |
| Usability | Responsive menu-based TUI for ordinary and phone-sized terminals plus a scriptable CLI. |
The goal is predictable operator control—not a claim that Tor is always fast, anonymous by itself, or guaranteed to exit in a selected country.
From a source checkout:
python -m pytest -q
python -m compileall -q xtorlib scripts tests
uvx ruff check xtorlib tests scripts
python -m xtorlib --help
python -m xtorlib tui --snapshot --no-color --width 80 --height 24Every release archive also needs its own checksum and manifest inspection, reproducibility check, staged lifecycle verification, and clean-host installation/uninstallation qualification.
If xTor is useful to you, donations are appreciated 🙏
| Network | Address |
|---|---|
| TRC20 (Tron) | TKBHWNoeygcaCK8N78e7dQX5Yco3WTb6ZN |
| BEP20 (BNB Smart Chain) | 0x0F982640a69D3B9FB944840D7DA8bECCfcF0bb9E |
| TON | UQAyLUyxew-eggwhxbzsAZZZ9ULM8MYOk-3IXFh7tNC33LNt |
Use the exact network shown for each address. Blockchain transactions are irreversible: verify the address in your wallet and send a small test transaction first.
xTor source is available under the MIT License. xTor is an independent project and must not imply endorsement by The Tor Project. “Tor” and related marks belong to The Tor Project.