Command-line interface for the Netcup Server Control Panel (SCP) REST API.
Manage servers, rDNS, snapshots, rescue systems, firewall policies, SSH keys, VLANs, and more from the terminal. Uses OAuth2 device-code flow; credentials are stored locally and refreshed automatically.
| Python | 3.9+ |
| License | MIT |
| API | SCP REST API · OpenAPI 2026.0218.151350 |
Why
netcupand notscp? The command is namednetcupto avoid clashing with the standard Unix scp (secure copy) command.
- Overview
- Requirements
- Installation
- Quick start
- Authentication
- Command reference
- Configuration
- Output and exit codes
- Troubleshooting
- API compatibility
- Project structure
- Getting help
- License
netcup CLI talks to the netcup SCP REST API. It supports:
- Servers — List, get, power on/off, set hostname/nickname; manage disks, interfaces, firewall, ISO, snapshots, rescue system, metrics, logs, image setup, guest agent, storage optimization.
- rDNS — Get, set, and delete reverse DNS for IPv4 and IPv6.
- Tasks — List (with filters), get, and cancel async tasks.
- Users — Current user info, get/update user; manage failover IPs, firewall policies, SSH keys, VLANs, user images/ISOs, logs.
- VLANs — Get VLAN by ID (standalone).
- Maintenance — Ping API and maintenance window info.
All commands that need a user context (e.g. users failoverips list) use the current user from your token by default; override with --user-id <id> when needed.
- Python 3.9 or newer
- Network access to
https://www.servercontrolpanel.de - A netcup SCP account (device-code login in the browser)
pip install netcup-clicd netcup-cli
pip install -e .After installation, the netcup command is available.
Development (lint, format, test) — using uv (recommended):
uv sync --all-extras # create venv + install deps including dev
uv run ruff check src tests # lint
uv run ruff format src tests # format
uv run ruff check src tests --fix # auto-fix lint
uv run pytest # testsWithout uv: pip install -e ".[dev]" then run ruff and pytest as above.
netcup --helpcd netcup-cli
pip install -r requirements.txt
PYTHONPATH=src python -m netcup_cli --helppipx install path/to/netcup-cli
# or after cloning:
pipx install -e path/to/netcup-cli-
Log in (opens browser for device code):
netcup auth login
Complete the flow in the browser; the CLI stores a refresh token under
~/.config/netcup-cli/. -
Check API:
netcup maintenance ping # OK -
List servers:
netcup servers list
-
Inspect one server:
netcup servers get <server_id>
-
Power control:
netcup servers power <server_id> on netcup servers power <server_id> off --option POWEROFF
-
rDNS:
netcup rdns ipv4 get 1.2.3.4 netcup rdns ipv4 set 1.2.3.4 host.example.com -
Current user:
netcup users info
For the full command set, see Command reference.
- Method: OAuth2 device code flow (no password in the CLI).
- Stored credential: Only the refresh token is saved; access tokens are obtained on demand and not written to disk.
- Location:
~/.config/netcup-cli/credentials(or$XDG_CONFIG_HOME/netcup-cli/credentialsif set). File format:{"refresh_token": "…"}. - Lifetime: Refresh token remains valid as long as it is used at least once every 30 days (per SCP API).
Commands:
| Command | Description |
|---|---|
netcup auth login |
Start device-code login; optionally --no-save to avoid storing the token. |
netcup auth logout |
Remove the stored credentials file. |
netcup auth revoke |
Revoke the current refresh token on the server and delete the local file. |
netcup auth show |
Print the path of the credentials file and whether it exists. |
Security:
- The credentials file should be readable only by the current user (the CLI sets mode
0600when possible). - Do not share the credentials file or the refresh token.
- Use
netcup auth revokeif the token may have been exposed.
--help,-h— Show help for the command or group.--version— Show netcup CLI version.
| Command | Description |
|---|---|
auth login [--no-save] |
Log in via device code; store refresh token unless --no-save. |
auth logout |
Remove stored credentials. |
auth revoke |
Revoke refresh token and remove credentials. |
auth show |
Show credentials file path and existence. |
| Command | Arguments / options | Description |
|---|---|---|
servers list |
[--limit N] [--offset N] [--ip IP] [--name NAME] [-q QUERY] |
List servers (optional filters). |
servers get <server_id> |
[--no-live] |
Get one server; --no-live skips live info. |
servers power <server_id> on|off |
[--option POWERCYCLE|RESET|POWEROFF] |
Power on/off or power cycle. |
servers set-hostname <server_id> <hostname> |
Set server hostname. | |
servers set-nickname <server_id> <nickname> |
Set server nickname. |
Disks: servers disks <server_id>
| Subcommand | Arguments | Description |
|---|---|---|
list |
<server_id> |
List disks. |
get |
<server_id> <disk_name> |
Get one disk. |
supported-drivers |
<server_id> |
List supported storage drivers. |
set-driver |
<server_id> VIRTIO|VIRTIO_SCSI|IDE|SATA |
Set disk driver. |
format |
<server_id> <disk_name> |
Format disk (data loss). |
Interfaces: servers interfaces <server_id>
| Subcommand | Arguments / options | Description |
|---|---|---|
list |
<server_id> [--no-rdns] |
List interfaces. |
get |
<server_id> <mac> [--no-rdns] |
Get interface by MAC. |
create |
<server_id> --vlan-id ID --driver DRIVER |
Create interface (VLAN); driver: VIRTIO, E1000, E1000E, RTL8139, VMXNET3. |
update |
<server_id> <mac> --body JSON |
Update interface (e.g. driver). |
delete |
<server_id> <mac> |
Delete interface. |
Firewall (per interface): servers firewall <server_id> <mac>
| Subcommand | Description |
|---|---|
get [--consistency-check] |
Get firewall config. |
put --body JSON |
Set firewall (copiedPolicies, userPolicies, active). |
reapply |
Reapply firewall. |
restore-copied-policies |
Restore copied policies. |
ISO: servers iso <server_id>
| Subcommand | Options | Description |
|---|---|---|
get |
Get attached ISO. | |
attach |
--iso-id ID or --user-iso NAME; [--boot-cdrom] |
Attach ISO. |
detach |
Detach ISO. | |
images |
List available ISO images for server. |
Snapshots: servers snapshots <server_id>
| Subcommand | Arguments / options | Description |
|---|---|---|
list |
<server_id> |
List snapshots. |
get |
<server_id> <name> |
Get one snapshot. |
create |
<server_id> --name NAME [--description DESC] [--disk-name NAME] [--online] |
Create snapshot. |
delete |
<server_id> <name> |
Delete snapshot. |
export |
<server_id> <name> |
Export snapshot. |
revert |
<server_id> <name> |
Revert to snapshot. |
dryrun |
<server_id> [--disk-name NAME] [--online] |
Check if snapshot creation is possible. |
Rescue system: servers rescue <server_id>
| Subcommand | Description |
|---|---|
get |
Get rescue system status. |
activate |
Activate rescue system. |
deactivate |
Deactivate rescue system. |
Metrics: servers metrics <server_id>
| Subcommand | Options | Description |
|---|---|---|
cpu |
[--hours N] |
CPU metrics. |
disk |
[--hours N] |
Disk metrics. |
network |
[--hours N] |
Network metrics. |
packet |
[--hours N] |
Network packet metrics. |
Other server commands
| Command | Arguments / options | Description |
|---|---|---|
servers logs list |
<server_id> [--limit N] [--offset N] |
Server logs. |
servers guest-agent get |
<server_id> |
Guest agent data. |
servers image flavours |
<server_id> |
Image flavours for setup. |
servers image setup |
<server_id> --body JSON |
Setup image (JSON body per API). |
servers user-image setup |
<server_id> --name NAME [--disk-name NAME] [--email-notification] |
Setup user image. |
servers storage-optimization start |
<server_id> [--disks NAME...] [--start-after] |
Start storage optimization. |
| Command | Example |
|---|---|
rdns ipv4 get <ip> |
netcup rdns ipv4 get 1.2.3.4 |
rdns ipv4 set <ip> <rdns> |
netcup rdns ipv4 set 1.2.3.4 host.example.com |
rdns ipv4 delete <ip> |
|
rdns ipv6 get <ip> |
|
rdns ipv6 set <ip> <rdns> |
|
rdns ipv6 delete <ip> |
| Command | Options | Description |
|---|---|---|
tasks list |
[--limit N] [--offset N] [-q QUERY] [--server-id ID] [--state STATE] |
List tasks. |
tasks get <uuid> |
Get one task. | |
tasks cancel <uuid> |
Cancel task. |
| Command | Options | Description |
|---|---|---|
users info |
Current user (from token). | |
users get <user_id> |
Get user by ID. | |
users update <user_id> --body JSON |
Update user (UserSave schema). |
All commands below support --user-id <id>; if omitted, the current user is used.
Failover IPs: users failoverips v4|v6
| Subcommand | Example |
|---|---|
v4 list |
[--ip IP] [--server-id ID] |
v4 route <id> <server_id> |
Route failover IPv4 to server. |
v6 list |
Same options as v4. |
v6 route <id> <server_id> |
Route failover IPv6 to server. |
Firewall policies: users firewall-policies
| Subcommand | Options |
|---|---|
list |
[--limit N] [--offset N] [-q QUERY] |
get <policy_id> |
[--with-servers-count] |
create --body JSON |
JSON: name, optional description, rules. |
update <policy_id> --body JSON |
|
delete <policy_id> |
SSH keys: users ssh-keys
| Subcommand | Options |
|---|---|
list |
|
add --name NAME --key KEY |
Add public key. |
delete <key_id> |
VLANs: users vlans
| Subcommand | Options |
|---|---|
list |
[--server-id ID] |
get <vlan_id> |
|
update <vlan_id> <name> |
User images (S3): users images
| Subcommand | Description |
|---|---|
list |
List user images. |
delete <key> |
Delete image by key. |
download-url <key> |
Get presigned download URL. |
User ISOs (S3): users isos
| Subcommand | Description |
|---|---|
list |
List user ISOs. |
delete <key> |
Delete ISO by key. |
download-url <key> |
Get presigned download URL. |
User logs: users logs list [--limit N] [--offset N]
| Command | Description |
|---|---|
vlans get <vlan_id> |
Get VLAN by ID (no user scope). |
| Command | Description |
|---|---|
maintenance ping |
Check API availability (returns OK). |
maintenance info |
Maintenance window information. |
- Path:
~/.config/netcup-cli/credentials(Linux/macOS). On Windows,%APPDATA%\netcup-cli\credentialsis not used by default; the CLI uses$XDG_CONFIG_HOMEif set, otherwise~/.config. - Override directory: Set
XDG_CONFIG_HOME(e.g.export XDG_CONFIG_HOME=$HOME/.config). - Format: JSON with a single key:
{"refresh_token": "…"}. Do not edit manually unless you know the token value.
The CLI uses these base URLs (not configurable via env or file):
- Auth:
https://www.servercontrolpanel.de/realms/scp/protocol/openid-connect - API root:
https://www.servercontrolpanel.de/scp-core/api - API v1:
https://www.servercontrolpanel.de/scp-core/api/v1
To point at another environment, you would need to change the code in netcup_cli/config.py.
- Success: Exit code
0. List/get commands print JSON to stdout (pretty-printed). - Failure: Exit code
1. Error message is printed to stderr (and often in red when run in a TTY). - JSON: All API responses that return JSON are printed as-is (indented). Use
jqfor further processing if needed, e.g.netcup servers list | jq '.[].name'.
- Cause: The server could not satisfy the
Acceptheader (e.g. endpoint returnstext/plainbut client asked forapplication/json). - Relevant command:
maintenance ping— fixed in current version by requestingAccept: text/plainfor that call. Ensure you use the latest code.
- Cause: No refresh token found in the credentials file.
- Fix: Run
netcup auth loginand complete the browser flow. Ensure the credentials file exists at the path shown bynetcup auth show.
- Cause: Refresh token expired or was revoked (e.g. after 30 days of no use, or revoked in SCP account).
- Fix: Run
netcup auth loginagain. If needed, revoke old access in SCP: Account → Applications → scp → Remove access, then log in again.
- Cause: You declined the authorization in the browser or closed the page before approving.
- Fix: Run
netcup auth loginagain and approve the application in the browser.
- Cause: You did not complete the browser step within the validity window (e.g. 600 seconds).
- Fix: Run
netcup auth loginagain and complete the flow promptly.
- Cause: Resource not found, validation error, or service temporarily unavailable (e.g. maintenance).
- Action: Check IDs and request body; for 503, retry later or check maintenance info:
netcup maintenance info.
- Spec: The CLI is built against the SCP REST API as described in the OpenAPI spec (version 2026.0218.151350 in the bundled
openapi.json). - Coverage: Most endpoints from the spec are implemented (servers, rDNS, tasks, users, failover IPs, firewall policies, SSH keys, VLANs, images/ISOs, logs, maintenance). Multipart upload for user images/ISOs is not implemented in the CLI.
- Breaking changes: If the API introduces breaking changes, the CLI may need updates. Check the netcup SCP API forum and release notes.
The file openapi.json in the project root is a snapshot of the spec fetched from:
curl -s -X GET 'https://www.servercontrolpanel.de/scp-core/api/v1/openapi' -H 'accept: application/json' -o openapi.jsonYou can refresh it to align with the latest API. The CLI does not read this file at runtime; it is for reference and code generation.
netcup-cli/
├── pyproject.toml # Package metadata, dependencies, entry point
├── requirements.txt # requests, click
├── README.md # This file
├── openapi.json # Snapshot of SCP OpenAPI spec
└── src/netcup_cli/
├── __init__.py # Version
├── config.py # URLs, credential path
├── auth.py # Device code, refresh, revoke, load/save credentials
├── client.py # HTTP client (Bearer token, Accept header)
├── exceptions.py # SCPError, AuthError, APIError, ConfigError
├── output.py # JSON formatting
├── api/ # API layer (one module per resource)
│ ├── base.py
│ ├── maintenance.py
│ ├── rdns.py
│ ├── servers.py
│ ├── servers_disks.py
│ ├── servers_interfaces.py
│ ├── servers_iso.py
│ ├── servers_snapshots.py
│ ├── servers_rescue.py
│ ├── servers_metrics.py
│ ├── servers_logs.py
│ ├── servers_image.py
│ ├── servers_guest.py
│ ├── servers_storage.py
│ ├── tasks.py
│ ├── users.py
│ ├── user_failoverips.py
│ ├── user_firewall_policies.py
│ ├── user_ssh_keys.py
│ ├── user_vlans.py
│ ├── user_images.py
│ ├── user_isos.py
│ └── user_logs.py
└── cli/ # Click commands
├── main.py # Entry point, group registration
├── helpers.py # user_id resolution
├── auth_cmd.py
├── servers_cmd.py
├── servers_disks_cmd.py
├── servers_interfaces_cmd.py
├── servers_iso_cmd.py
├── servers_snapshots_cmd.py
├── servers_rescue_cmd.py
├── servers_metrics_cmd.py
├── servers_misc_cmd.py
├── rdns_cmd.py
├── tasks_cmd.py
├── users_cmd.py
├── users_resources_cmd.py
├── vlans_cmd.py
└── maintenance_cmd.py
- General:
netcup --help - Command group:
netcup servers --help,netcup users --help, etc. - Specific command:
netcup servers power --help,netcup rdns ipv4 set --help - Version:
netcup --version
MIT. See the LICENSE file in the project repository for the full license text.