Skip to content

pavelpikta/netcup-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Netcup Server Control Panel (SCP) CLI

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 netcup and not scp? The command is named netcup to avoid clashing with the standard Unix scp (secure copy) command.


Table of contents


Overview

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.


Requirements

  • Python 3.9 or newer
  • Network access to https://www.servercontrolpanel.de
  • A netcup SCP account (device-code login in the browser)

Installation

From PyPI (when published)

pip install netcup-cli

From source (development or unreleased)

cd 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                 # tests

Without uv: pip install -e ".[dev]" then run ruff and pytest as above.

netcup --help

Without installing (run as module)

cd netcup-cli
pip install -r requirements.txt
PYTHONPATH=src python -m netcup_cli --help

Optional: use pipx (isolated environment)

pipx install path/to/netcup-cli
# or after cloning:
pipx install -e path/to/netcup-cli

Quick start

  1. 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/.

  2. Check API:

    netcup maintenance ping
    # OK
  3. List servers:

    netcup servers list
  4. Inspect one server:

    netcup servers get <server_id>
  5. Power control:

    netcup servers power <server_id> on
    netcup servers power <server_id> off --option POWEROFF
  6. rDNS:

    netcup rdns ipv4 get 1.2.3.4
    netcup rdns ipv4 set 1.2.3.4 host.example.com
  7. Current user:

    netcup users info

For the full command set, see Command reference.


Authentication

  • 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/credentials if 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 0600 when possible).
  • Do not share the credentials file or the refresh token.
  • Use netcup auth revoke if the token may have been exposed.

Command reference

Global options

  • --help, -h — Show help for the command or group.
  • --version — Show netcup CLI version.

netcup auth

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.

netcup servers

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.

netcup rdns

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>

netcup tasks

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.

netcup users

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]


netcup vlans

Command Description
vlans get <vlan_id> Get VLAN by ID (no user scope).

netcup maintenance

Command Description
maintenance ping Check API availability (returns OK).
maintenance info Maintenance window information.

Configuration

Credentials

  • Path: ~/.config/netcup-cli/credentials (Linux/macOS). On Windows, %APPDATA%\netcup-cli\credentials is not used by default; the CLI uses $XDG_CONFIG_HOME if 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.

API endpoints (hardcoded)

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.


Output and exit codes

  • 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 jq for further processing if needed, e.g. netcup servers list | jq '.[].name'.

Troubleshooting

API error: 406

  • Cause: The server could not satisfy the Accept header (e.g. endpoint returns text/plain but client asked for application/json).
  • Relevant command: maintenance ping — fixed in current version by requesting Accept: text/plain for that call. Ensure you use the latest code.

No stored credentials. Run: netcup auth login

  • Cause: No refresh token found in the credentials file.
  • Fix: Run netcup auth login and complete the browser flow. Ensure the credentials file exists at the path shown by netcup auth show.

Token refresh failed: 401 or 403

  • Cause: Refresh token expired or was revoked (e.g. after 30 days of no use, or revoked in SCP account).
  • Fix: Run netcup auth login again. If needed, revoke old access in SCP: Account → Applications → scp → Remove access, then log in again.

Access denied on device authorization

  • Cause: You declined the authorization in the browser or closed the page before approving.
  • Fix: Run netcup auth login again and approve the application in the browser.

Device code expired

  • Cause: You did not complete the browser step within the validity window (e.g. 600 seconds).
  • Fix: Run netcup auth login again and complete the flow promptly.

API error: 404 / 422 / 503

  • 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.

API compatibility

  • 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.

OpenAPI spec file

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.json

You 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.


Project structure

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

Getting help

  • 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

License

MIT. See the LICENSE file in the project repository for the full license text.


Links

About

Command-line interface for the Netcup Server Control Panel (SCP) REST API

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages