Skip to main content

Secure LAN-based remote PC control and administration

Project description

remctl

Secure, LAN-based remote PC control and administration.

remctl lets you control machines on your local network from the command line — lock, shutdown, execute shell commands with streaming output, transfer files, take screenshots, and check system status. All communication is authenticated using Ed25519 keys and encrypted with AES-256-GCM.

⚠️ Intended for your own trusted LAN devices only. remctl is not designed for Internet-facing use. Do not expose it via port forwarding or NAT.

Installation

pip install remctl

From source

# TODO: user adds PyPI API token via env var / twine config before publishing
git clone <repo-url>
cd remctl
pip install -e ".[dev]"

Quick Start (Easy Mode)

On the target machine (the node)

# First run starts a short setup wizard (name, admin, acceptance mode),
# then runs the agent in the foreground:
remctl node start

The wizard asks three things:

  1. Node name — a friendly name broadcast on your LAN (e.g. livingroom-pc).
  2. Allow admin (exec/shell) commands? — grants the full tier to new controllers, otherwise they get standard (no exec).
  3. Acceptance mode for new controllers:
    • auto — trust any controller that connects (easiest, least safe)
    • ask — ask for approval on every connection
    • ask-new — ask only the first time a controller connects (recommended)

You can re-run the wizard any time with remctl node setup, or start without it using the stored config via remctl node start.

On the controlling machine

# Find nodes on the LAN (lists them by name)
remctl ctl scan

# Connect to one by name — this pairs it and makes it the active node
remctl ctl connect livingroom-pc

# Now run actions on the active node
remctl ctl actions list                       # what can I do?
remctl ctl actions status
remctl ctl actions lock
remctl ctl actions shutdown --delay 60
remctl ctl shell "whoami"                      # = actions exec

If you have more than one node, target a specific one with --node:

remctl ctl actions status --node bedroom-pc
remctl ctl nodes                               # list paired nodes + active
remctl ctl forget livingroom-pc                # remove a paired node

Advanced: Manual Two-Way Pairing

If you prefer explicit key exchange (no acceptance-mode prompts), use the original flow. Both sides must still trust each other:

# Node: show its fingerprint
remctl node pair --show
remctl node start

# Controller: pair + show its own fingerprint for the node to trust
remctl ctl pair <node-ip>
remctl ctl pair-show

# Node: trust the controller's public key file
remctl node trust-controller /path/to/controller_identity.pub

Legacy per-command form (still works, defaults to the active node):

remctl ctl <target> status
remctl ctl <target> lock
remctl ctl <target> exec "whoami"
remctl ctl <target> screenshot -o screenshot.png
remctl ctl <target> push ./file.txt /remote/path/file.txt
remctl ctl <target> pull /remote/log.log ./log.log

Command Reference

Command Description
remctl node start First-run wizard (if needed) then start the node agent
remctl node setup Run the setup wizard (name, admin, acceptance mode)
remctl node install-service Install as OS service
remctl ctl scan Discover nodes on the LAN (by name)
remctl ctl connect <name> Pair with a node and make it active
remctl ctl nodes List paired nodes + active
remctl ctl forget <name> Remove a paired node
remctl ctl actions list List available actions + tiers
remctl ctl actions <action> [--node <name>] Run a named action on the active node
remctl ctl shell "<cmd>" Alias for actions exec
remctl ctl discover Discover nodes on LAN (legacy)
remctl ctl pair <target> Pair with a node (manual flow)
remctl ctl <target> lock Lock the remote workstation
remctl ctl <target> shutdown --delay 60 Shutdown with optional delay
remctl ctl <target> restart Restart
remctl ctl <target> sleep Sleep/Suspend
remctl ctl <target> logout Log out current user
remctl ctl <target> closefocused Close active window
remctl ctl <target> exec <command> Execute shell command (streamed)
remctl ctl <target> status Show system status (CPU/mem/disk/uptime)
remctl ctl <target> screenshot -o out.png Capture screenshot
remctl ctl <target> push <local> <remote> Push file to node
remctl ctl <target> pull <remote> <local> Pull file from node
remctl ctl <target> cancel Cancel pending shutdown/restart

Security Model (Summary)

  • Identity: Ed25519 keypairs generated on first run.
  • Authentication: Node accepts controllers per its acceptance mode (auto / ask / ask-new). Default is ask-new — no auto-trust unless you opt in. The manual two-way trust-controller flow still works.
  • Encryption: X25519 ECDH key exchange → AES-256-GCM, with forward secrecy.
  • Replay protection: Per-message sequence numbers + 30-second timestamp window.
  • Permission tiers: observe (status/screenshot), standard (commands + files), full (includes exec). Default for new controllers: standard.
  • Audit log: All commands logged unredacted at ~/.remctl/audit.log.

See docs/SECURITY.md for the full threat model.

Configuration

All config files live in ~/.remctl/:

File Purpose
identity.key Private key (keep secure)
identity.pub Public key
known_nodes.json Paired nodes (ctl side)
known_controllers.json Trusted controllers (node side)
node_config.json Node settings (name, bind, port, acceptance mode, tiers)
ctl_config.json Controller settings (active node)
audit.log Command audit log

Platform Support

Platform Status
Windows First-class
Linux Second-class (best-effort)
macOS Not yet implemented

Publishing to PyPI

python -m build
twine upload dist/*

You need a PyPI API token (not your password):

  1. Create a free account at https://pypi.org
  2. Go to https://pypi.org/manage/account/token/ and generate a token scoped to remctl
  3. Copy .env.example to .env and fill in the token, or set these env vars:
export TWINE_USERNAME=__token__
export TWINE_PASSWORD=pypi-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

See .env.example for the full list of configurable secrets. No credentials are included in the repository.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

remctl-0.1.1.tar.gz (31.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

remctl-0.1.1-py3-none-any.whl (32.4 kB view details)

Uploaded Python 3

File details

Details for the file remctl-0.1.1.tar.gz.

File metadata

  • Download URL: remctl-0.1.1.tar.gz
  • Upload date:
  • Size: 31.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for remctl-0.1.1.tar.gz
Algorithm Hash digest
SHA256 1cefc1a1fc261475171e5dfb8d518fcea0f0f765f78579f572d9063a77cb1385
MD5 c0e9ba7e65b7568b5e0ec39116923788
BLAKE2b-256 6b034f23ce737ce4b13d7a21915a28e6e8917847508a4ef8ff5af7f373a6d5e1

See more details on using hashes here.

File details

Details for the file remctl-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: remctl-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 32.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for remctl-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 eba9c97e5ff6df7de0ec85398197d9c08338ef4f3635ba34f380eb4e60731579
MD5 c07efb252b9846b4fdb4c2b90b14b406
BLAKE2b-256 36e9f26b12e9961c643593bb8014908194e03dbdc5db4f89d311dd0f0aa5baa6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page