# Netcup Server Provisioning — Initial Setup Covers provisioning a fresh Netcup RS VPS (Manassas) — from order confirmation email to secure, usable server. ## SCP REST API Authentication The Netcup SCP (Server Control Panel) provides a REST API at `https://www.servercontrolpanel.de/scp-core/api/v1/`. This is distinct from the CCP (Customer Control Panel) API. ### Auth Flow The SCP uses Keycloak (OIDC) for authentication, NOT the CCP API key / API password method. **Correct auth flow (password grant):** ```bash # Step 1: Get token curl -s "https://www.servercontrolpanel.de/realms/scp/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=password&client_id=scp&username=${CUSTOMER_NUMBER}&password=${CCP_PASSWORD}" \ -o /tmp/netcup_token.json TOKEN=$(jq -r '.access_token' /tmp/netcup_token.json) # Step 2: Use token curl -s "https://www.servercontrolpanel.de/scp-core/api/v1/servers" \ -H "Authorization: Bearer ${TOKEN}" ``` **⚠️ Cron mode:** `python3 -c` and `curl | python3` are blocked by the security scanner in cron. Use `jq` (as shown above) and two-step file approach instead of pipes. ### Key Details | Parameter | Value | |-----------|-------| | Auth URL | servercontrolpanel.de/realms/scp/protocol/openid-connect/token | | Client ID | scp (from SCP web app) | | Grant type | password | | Username | Customer number (e.g. 389212) -- NOT the CCP API key | | Password | CCP login password -- NOT the API password | | Token lifetime | 300 seconds (5 min) | | API base | servercontrolpanel.de/scp-core/api/v1/ | | Auth header | Authorization: Bearer | ### Auth Pitfalls - The CCP API Key + API Password from Master Data are for a DIFFERENT API (DNS/domain management via XML-RPC) - The SCP REST API uses the CCP LOGIN credentials (customer number + password), not the API keys - Make sure the server's IP is whitelisted in SCP -> REST API Settings, or leave the whitelist empty to allow all - The X-API-Key header does NOT work with the SCP API -- only Authorization: Bearer with an OIDC token - The correct API path is /scp-core/api/ -- NOT /scp-ui/api/ (which serves the web UI, not data) - scp-ui/api/v1/servers returns the HTML login page instead of JSON -- this is how it behaves when auth is missing ### Available Endpoints (from this account) | Endpoint | Purpose | Works? | |----------|---------|--------| | GET /scp-core/api/v1/servers | List all servers | Yes | | GET /scp-core/api/v1/servers/{id} | Server details | Yes | | POST /scp-core/api/v1/templates | Provisioning | Not found | The provisioning endpoints (/templates, /images) may be scoped to reseller/partner accounts only. Standard customer accounts can create/view servers but not provision new ones via API. ## After Order Approval Netcup sends two emails: 1. **SCP access** — `https://www.servercontrolpanel.de/SCP/` with username + password 2. **Server ready** — IP address, root password, hostname, OS info ### Data Processing Agreement (DPA) New accounts must complete a DPA before payment processes. Standard EU GDPR boilerplate: - Navigate CCP → Master Data → Order Processing - "Conclude Data Processing Agreement" — pre-filled standard text, just review and accept - Netcup acts as processor (Art. 28 GDPR), you as controller - Required even for US businesses with US customers in Manassas ## First SSH — Do NOT change root password before capturing it **CRITICAL PITFALL:** Do NOT change the root password inside the same SSH command that creates users. If the command errors mid-way (e.g. package install fails), the new password was set but never captured in the output. The original email password no longer works, and the server is unreachable. **Correct procedure:** ```bash # Step 1: SSH in with original password, deploy SSH key immediately sshpass -p '' ssh -o StrictHostKeyChecking=accept-new root@ ' set -e mkdir -p /root/.ssh && chmod 700 /root/.ssh ' # Pipe the SSH key in a separate step sshpass -p '' ssh root@ 'cat >> /root/.ssh/authorized_keys' < ~/.ssh/wisp_rsa.pub # Step 2: Test key-based auth, THEN create users + change passwords ssh -i ~/.ssh/wisp_rsa root@ ' useradd -m -s /bin/bash -G sudo ippadmin echo "ippadmin ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ippadmin mkdir -p /home/ippadmin/.ssh && chmod 700 /home/ippadmin/.ssh cat /root/.ssh/authorized_keys >> /home/ippadmin/.ssh/authorized_keys chown -R ippadmin:ippadmin /home/ippadmin/.ssh && chmod 600 /home/ippadmin/.ssh/authorized_keys ROOT_PASS=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 20) echo "root:${ROOT_PASS}" | chpasswd echo "New root password: ${ROOT_PASS}" ' ``` ## Debian 13 (Trixie) Package Names Netcup deploys Debian 13 (Trixie) minimal by default. Package names differ from Debian 12: | Package | Notes | |---------|-------| | docker.io | Available (Docker 26.1.5) | | docker-compose-plugin | NOT in Debian 13 repos — must use Docker's apt repo | | python3-pip | Available | | python3-venv | May need `python3.13-venv` | | ufw | Available | | gnupg | Not pre-installed, needed for apt-key management | | unzip | Not pre-installed | | awscli v2 | Must install manually via `curl + unzip` | ### Docker Compose — Dedicated apt repo ```bash apt-get install -y gnupg curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian bookworm stable" | tee /etc/apt/sources.list.d/docker.list apt-get update && apt-get install -y docker-compose-plugin ``` Use **bookworm** (Debian 12 codename), not trixie — Docker doesn't have a trixie-specific repo yet. The bookworm packages work on trixie. ### AWS CLI v2 ```bash curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip apt-get install -y unzip unzip -q /tmp/awscliv2.zip -d /tmp/ /tmp/aws/install --update rm -rf /tmp/aws /tmp/awscliv2.zip ``` ### Wasabi S3 Credentials ```bash aws configure set aws_access_key_id GYH83FP0KL0K85N60JKQ aws configure set aws_secret_access_key aws configure set region us-east-1 chmod 600 /root/.aws/credentials # Test — note: s3:ListAllMyBuckets is NOT supported by Wasabi IAM aws s3 ls s3://hermes-vps-backups/ --endpoint-url https://s3.us-east-1.wasabisys.com ``` ### Hermes ```bash curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash ``` ## Standard Netcup SCP - URL: `https://www.servercontrolpanel.de/SCP/` - Use for: password resets, firewall policy management, OS reinstall, boot/rescue mode - Netcup pre-installs a firewall policy that blocks SMTP. Remove "netcup Mail Block" policy in SCP → Firewall if email delivery is needed. ## Standard Admin User All servers use `ippadmin` (sudo, no password) with the `wisp_rsa` Ed25519 SSH key. Root SSH login should be disabled after setup: ```bash sed -i 's/^PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config systemctl restart sshd ``` ## Firewall (UFW) ```bash ufw default deny incoming ufw default allow outgoing ufw allow ssh ufw allow http ufw allow https ufw --force enable ``` ## Root password safety rule When setting up a new remote server: 1. Connect with the provided password 2. **Immediately deploy your SSH public key** first 3. Then create users, install packages, change passwords 4. Record new passwords in password manager 5. Use SSH key for all future access **Never change root password mid-script without capturing the output.** If the script fails before `echo "password: ${PASS}"` executes, you're locked out.