Add Your First Server
Learn how to add and configure your first server on OEC.SH. This guide covers BYOS (Bring Your Own Server) setup, server requirements, authentication methods, and connection verification.
Overview
Servers are the infrastructure backbone of your OEC.SH deployment. Each server can host multiple Odoo environments (typically 3-10 environments per server depending on resources). OEC.SH supports a BYOS (Bring Your Own Server) model, giving you complete control over your infrastructure while benefiting from our automated deployment and management platform.
What You'll Learn
- Server requirements and specifications
- BYOS setup and preparation
- Adding a server to OEC.SH
- Connection verification and health checks
- Converting password auth to SSH key auth (One-Click Secure)
- Server monitoring setup with Netdata
- Troubleshooting common issues
Why BYOS?
Cost Savings: Use your existing infrastructure or choose the most cost-effective provider. Save 50% or more compared to managed Odoo hosting.
Data Sovereignty: Keep your data in your preferred region or datacenter. Full compliance with GDPR and other regulations.
Flexibility: Choose any Linux server from any provider - DigitalOcean, AWS, Hetzner, OVH, or even on-premises servers.
No Vendor Lock-in: Your servers, your data, your control. Migrate between providers anytime.
Prerequisites
Before adding your first server, ensure you have:
- Active OEC.SH Account: Sign up at app.oec.sh (opens in a new tab)
- Organization Created: Automatically created on signup (see Account Setup)
- Permission:
org.servers.createpermission in your organization - Server Access: Root or sudo user access to a Linux server
- Basic Linux Knowledge: Familiarity with SSH and command-line operations
Server Requirements
Minimum Specifications
For development and testing environments:
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 4 GB | 8+ GB |
| Disk | 50 GB | 100+ GB SSD |
| Network | 1 Gbps | 1 Gbps+ |
Recommended Specifications
For production workloads:
| Server Size | CPU Cores | RAM | Disk | Max Environments |
|---|---|---|---|---|
| Small | 2 cores | 4 GB | 80 GB | 3-5 environments |
| Medium | 4 cores | 8 GB | 160 GB | 5-8 environments |
| Large | 8 cores | 16 GB | 320 GB | 8-10 environments |
| X-Large | 16+ cores | 32+ GB | 500+ GB | 10+ environments |
Operating System Support
Fully Supported (Tier 1):
- Ubuntu 20.04 LTS (Focal)
- Ubuntu 22.04 LTS (Jammy)
- Ubuntu 24.04 LTS (Noble)
- Debian 11 (Bullseye)
- Debian 12 (Bookworm)
Partially Supported (Tier 2):
- Rocky Linux 8/9
- AlmaLinux 8/9
- CentOS Stream 8/9
Not Supported:
- Alpine Linux (limited systemd support)
- Arch Linux (rolling release instability)
- Windows Server (not compatible)
Required Software
- Docker: Version 20.10 or higher
- SSH Server: OpenSSH 7.0+ (usually pre-installed)
- systemd: For service management
- curl/wget: For downloads and API calls
Network Requirements
Required Ports:
22- SSH access (inbound)80- HTTP traffic (inbound)443- HTTPS traffic (inbound)6432- PostgreSQL/PgBouncer (internal, optional external)8069- Odoo HTTP (internal only)
Optional Ports:
19999- Netdata monitoring dashboard6433- PostgreSQL read replica (if using replicas)
Firewall Configuration: Allow inbound traffic on ports 22, 80, and 443. All other ports can be internal-only.
BYOS Setup Guide
Step 1: Provision a Server
Choose your preferred cloud provider or use an on-premises server:
Popular Providers:
DigitalOcean (Recommended for beginners):
# Example: Create a 4GB droplet in Frankfurt
doctl compute droplet create paasportal-prod-1 \
--region fra1 \
--size s-2vcpu-4gb-intel \
--image ubuntu-22-04-x64 \
--ssh-keys <your-ssh-key-id>Hetzner Cloud (Best price/performance):
# Example: Create a CX31 server (2 vCPU, 8GB RAM)
hcloud server create \
--name paasportal-prod-1 \
--type cx31 \
--image ubuntu-22.04 \
--location fsn1AWS EC2:
# Example: Launch a t3.medium instance
aws ec2 run-instances \
--image-id ami-0c55b159cbfafe1f0 \
--instance-type t3.medium \
--key-name your-key-pair \
--security-groups paasportal-sg \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=paasportal-prod-1}]'Step 2: Initial Server Access
Connect to your server via SSH:
# Using password (temporary)
ssh root@your-server-ip
# Or using SSH key (recommended)
ssh -i ~/.ssh/your-key.pem root@your-server-ipStep 3: Update System Packages
Always start with a fresh system update:
# Ubuntu/Debian
sudo apt update && sudo apt upgrade -y
# Rocky/AlmaLinux/CentOS
sudo dnf update -yStep 4: Install Docker
OEC.SH requires Docker 20.10 or higher. Use our automated installation script:
Ubuntu/Debian:
# Download and run Docker installation script
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Start and enable Docker service
sudo systemctl start docker
sudo systemctl enable docker
# Verify installation
docker --version
# Expected output: Docker version 24.0.x or higherRocky/AlmaLinux/CentOS:
# Install Docker from official repository
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io -y
# Start and enable Docker service
sudo systemctl start docker
sudo systemctl enable docker
# Verify installation
docker --versionVerify Docker is Running:
# Check Docker service status
sudo systemctl status docker
# Test Docker with hello-world
docker run hello-world
# Expected: "Hello from Docker!" messageStep 5: Configure Firewall
UFW (Ubuntu/Debian):
# Install UFW if not present
sudo apt install ufw -y
# Allow SSH (IMPORTANT: Do this first!)
sudo ufw allow 22/tcp
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Optional: Allow Netdata monitoring
sudo ufw allow 19999/tcp
# Enable firewall
sudo ufw enable
# Verify rules
sudo ufw statusfirewalld (Rocky/AlmaLinux/CentOS):
# Start firewalld
sudo systemctl start firewalld
sudo systemctl enable firewalld
# Allow required ports
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
# Reload firewall
sudo firewall-cmd --reload
# Verify rules
sudo firewall-cmd --list-allStep 6: Create SSH User (Optional but Recommended)
For better security, create a dedicated user instead of using root:
# Create user
sudo useradd -m -s /bin/bash paasportal
# Set password (temporary, will switch to SSH key later)
sudo passwd paasportal
# Grant sudo privileges (NOPASSWD for automated operations)
echo "paasportal ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/paasportal
# Test sudo access
sudo -u paasportal sudo whoami
# Expected output: rootStep 7: Verify Prerequisites
Run this verification script to check all requirements:
#!/bin/bash
echo "=== OEC.SH Server Prerequisites Check ==="
# Check OS
echo "OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)"
# Check resources
echo "CPU Cores: $(nproc)"
echo "RAM: $(free -h | awk '/^Mem:/ {print $2}')"
echo "Disk: $(df -h / | awk 'NR==2 {print $2}')"
# Check Docker
if command -v docker &> /dev/null; then
echo "Docker: $(docker --version)"
if systemctl is-active docker &> /dev/null; then
echo "Docker Status: Running ✓"
else
echo "Docker Status: Not running ✗"
fi
else
echo "Docker: Not installed ✗"
fi
# Check connectivity
echo "SSH Port: $(ss -tlnp | grep ':22' | wc -l) listener(s)"
echo "=== Check Complete ==="Save as check-prerequisites.sh, make executable, and run:
chmod +x check-prerequisites.sh
./check-prerequisites.shAdd Server to OEC.SH
Now that your server is prepared, let's add it to OEC.SH.
Step 1: Navigate to Servers Page
- Log in to app.oec.sh (opens in a new tab)
- Select your organization from the top navigation
- Click Servers in the left sidebar
- Click the Add Server button in the top right

Step 2: Fill Server Details
The Add Server modal contains several sections:
Basic Information
Server Name: A friendly name to identify your server
Examples:
- production-server-1
- dev-fra1
- staging-us-east
- odoo-prod-hetznerRegion/Location: Geographic location of your server
Examples:
- Frankfurt, Germany
- New York, USA
- Singapore
- CustomProvider: Select your cloud provider or "Custom" for any Linux server
- DigitalOcean
- AWS
- Hetzner
- Azure
- Custom (any Linux server)
Connection Details
Connection Type: Choose how to connect to your server
IPv4 Address (Recommended):
Example: 203.0.113.100IPv6 Address (Optional):
Example: 2a03:b0c0:3:d0::1af1:1FQDN (Optional but recommended for production):
Example: server1.yourdomain.comConnection Host Type: Determines which address to use
auto- Try FQDN > IPv4 > IPv6 > Hostname (recommended)ipv4- Always use IPv4 addressipv6- Always use IPv6 addressfqdn- Always use FQDN
SSH Port: Usually 22 (change if using non-standard port)
Default: 22
Custom: 2222, 22000, etc.SSH Username: User with root or sudo access
Common usernames:
- root (most VPS providers)
- ubuntu (AWS, some DigitalOcean images)
- admin (some providers)
- paasportal (if you created custom user)Authentication Method
OEC.SH supports two authentication methods:
Option 1: Password Authentication (Quick Start)
Best for initial setup. You can upgrade to SSH key later using "One-Click Secure".
SSH Password: Your server's root/sudo password
Note: Password is encrypted before storage using AES-256When to use:
- Quick onboarding
- Testing/development servers
- Will upgrade to SSH key authentication later
Option 2: SSH Key Authentication (Recommended)
Most secure method. Required for production servers.
SSH Private Key: Your private key in PEM format
Generate a new SSH key (if you don't have one):
# Generate Ed25519 key (recommended - smaller, faster, more secure)
ssh-keygen -t ed25519 -C "paasportal-server1" -f ~/.ssh/paasportal-server1
# Or generate RSA key (compatible with older systems)
ssh-keygen -t rsa -b 4096 -C "paasportal-server1" -f ~/.ssh/paasportal-server1Deploy public key to server:
# Copy public key to server
ssh-copy-id -i ~/.ssh/paasportal-server1.pub root@your-server-ip
# Or manually append to authorized_keys
cat ~/.ssh/paasportal-server1.pub | ssh root@your-server-ip \
"mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"Copy private key and paste into OEC.SH:
# Display private key
cat ~/.ssh/paasportal-server1
# Copy the entire output including:
# -----BEGIN OPENSSH PRIVATE KEY-----
# ... key content ...
# -----END OPENSSH PRIVATE KEY-----SSH Key Passphrase (Optional): If your key is encrypted, provide passphrase
When to use:
- Production servers
- Maximum security
- Compliance requirements
- Automated operations
Resource Allocation
CPU Cores: Number of CPU cores (auto-detected after connection)
Examples:
- 2 cores (small/dev)
- 4 cores (medium/staging)
- 8 cores (large/production)Memory (GB): RAM in gigabytes (auto-detected)
Examples:
- 4 GB (small)
- 8 GB (medium)
- 16 GB (large)Disk (GB): Root partition size (auto-detected)
Examples:
- 80 GB (small)
- 160 GB (medium)
- 320 GB (large)Max Environments: Maximum environments allowed on this server
Recommendation:
- 2 GB RAM per environment minimum
- 4 GB server = 3-5 environments max
- 8 GB server = 5-8 environments max
- 16 GB server = 8-10 environments maxStep 3: Test Connection
Before saving, click Test Connection to verify:
Connection Test Checks:
- ✅ SSH connectivity on specified port
- ✅ Authentication (password or SSH key)
- ✅ Sudo/root access verification
- ✅ Operating system detection
- ✅ Docker installation and version check
- ✅ Resource detection (CPU, RAM, disk)
- ✅ Network connectivity
Expected Response:
{
"status": "success",
"message": "Connection successful",
"detected": {
"hostname": "ubuntu-s-2vcpu-4gb-fra1-01",
"os_type": "Ubuntu",
"os_version": "22.04",
"docker_status": "running",
"docker_version": "24.0.7",
"cpu_cores": 2,
"memory_gb": 4,
"disk_gb": 80,
"provider": "digitalocean",
"region": "Frankfurt 1",
"is_root": false,
"sudo_available": true,
"ssh_sudo_mode": "sudo"
}
}Connection Status Indicators:
- 🟢 Healthy: All checks passed
- 🟡 Needs Setup: Docker not installed (can be auto-fixed)
- 🔴 Error: Authentication failed or unreachable
- ⚪ Unknown: Not yet tested
Step 4: Save Server
If connection test is successful, click Add Server.
What Happens Next:
- Server record created in database
- SSH credentials encrypted and stored
- Server health check scheduled (every 5 minutes)
- Server appears in Servers list
- Ready for environment deployment

Connection Verification
After adding your server, OEC.SH performs automatic verification and health checks.
Automatic OS Detection
OEC.SH detects your operating system details:
Detected Information:
- OS family (Debian, RHEL, Alpine)
- OS name (Ubuntu, Rocky Linux, CentOS)
- OS version (22.04, 8, 9)
- Kernel version (5.15.0-91-generic)
- Init system (systemd, openrc)
- Package manager (apt, dnf, yum)
Detection Process:
# OEC.SH runs these commands via SSH
cat /etc/os-release
uname -r
command -v systemctl || command -v openrc-runDocker Status Check
Docker Detection:
# Check Docker version
docker --version
# Check Docker daemon status
sudo systemctl status docker
# Test Docker functionality
docker infoDocker Statuses:
- ✅ Running: Docker daemon active and healthy
- ⚠️ Not Installed: Docker missing (auto-install available)
- ❌ Error: Docker installed but not running
- ⚪ Unknown: Cannot determine status
Resource Detection
OEC.SH auto-detects server resources:
CPU Detection:
# Number of CPU cores
nproc
# Example output: 4Memory Detection:
# Total RAM in GB (rounded up)
awk '/^MemTotal:/{printf "%.0f", $2/1024/1024 + 0.5}' /proc/meminfo
# Example output: 8Disk Detection:
# Root partition size in GB
df -BG / | awk 'NR==2{print $2}' | tr -d 'G'
# Example output: 160Provider Detection
OEC.SH attempts to detect your cloud provider from hostname patterns:
DigitalOcean Pattern:
ubuntu-s-2vcpu-4gb-intel-fra1-01
^
Provider detected: digitalocean
Region detected: Frankfurt 1Hetzner Pattern:
ubuntu-4gb-hel1-1
^
Provider detected: hetzner
Region detected: HelsinkiAWS Pattern:
ip-172-31-45-123
^
Provider detected: awsCustom Servers: If pattern doesn't match, provider remains "custom"
Health Status
Health Check Frequency: Every 5 minutes (configurable)
Health Statuses:
- 🟢 Healthy: Server reachable, all services running
- 🟡 Degraded: Reachable but services have issues
- 🔴 Unhealthy: Server unreachable or critical errors
- 🔴 Auth Failed: SSH authentication failing
- ⚪ Unknown: Never checked or check pending
Server Dashboard
View complete server details in the server dashboard:
Monitoring Metrics:
- Connection status and last check time
- Resource utilization (CPU, RAM, disk)
- Deployed environments count
- Docker version and status
- OS details and version
- Network information (IPs, hostname, FQDN)
- Authentication method and security status

One-Click Secure Server
Convert your server from password authentication to SSH key authentication with one click.
Why SSH Keys Are More Secure
Password Authentication Risks:
- ❌ Vulnerable to brute force attacks
- ❌ Can be intercepted (if not using strong encryption)
- ❌ Human-memorable passwords are often weak
- ❌ Shared passwords compromise multiple systems
SSH Key Authentication Benefits:
- ✅ Cryptographically strong (256-bit Ed25519 or 4096-bit RSA)
- ✅ Immune to brute force attacks
- ✅ Keys can be easily rotated
- ✅ Supports key-per-server isolation
- ✅ Required for compliance (PCI-DSS, SOC 2, HIPAA)
How One-Click Secure Works
Behind the Scenes:
- Generate new Ed25519 SSH key pair
- Connect to server using current password
- Deploy public key to
~/.ssh/authorized_keys - Verify key-based authentication works
- Update OEC.SH to use SSH key
- Clear password from database
- (Optional) Disable password auth on server
Process Duration: 10-30 seconds
Performing One-Click Secure
Step 1: Navigate to server details
Step 2: Look for the "Password Auth" badge (yellow/orange)

Step 3: Click Secure Server button
Step 4: Confirm security upgrade
Options:
- ☐ Download private key backup (recommended)
- ☐ Disable password authentication on server (optional, very secure)
Step 5: Click Secure Now
Progress Indicators:
1. Generating SSH key pair...
2. Connecting to server...
3. Deploying public key...
4. Verifying key authentication...
5. Updating server credentials...
✓ Server successfully secured!Step 6: Download private key backup
CRITICAL: Save this key securely. It's the ONLY time you'll see it.
# Save to secure location
mkdir -p ~/.ssh/oecsh-backups
mv ~/Downloads/paasportal-server1-private-key.pem \
~/.ssh/oecsh-backups/server1.pem
chmod 600 ~/.ssh/oecsh-backups/server1.pemStep 7: Verify security upgrade
Server badge changes from "Password Auth" to "Secured" (green).

After Securing
What Changed:
- ✅ Server now uses SSH key authentication
- ✅ Password cleared from OEC.SH database
- ✅ Public key added to server's
authorized_keys - ✅ Connection verified with new key
- ✅ All future operations use secure key auth
Can I Still SSH Manually?: Yes, if you chose "Disable password auth on server", you must use keys:
# Won't work anymore
ssh root@your-server-ip
# Error: Permission denied (publickey)
# Must use the OEC.SH key or your own keys
ssh -i ~/.ssh/oecsh-backups/server1.pem root@your-server-ipKey Rotation: You can generate new keys anytime in server settings
Server Monitoring Setup
OEC.SH integrates Netdata for real-time infrastructure monitoring.
What is Netdata?
Netdata is an open-source, real-time performance monitoring tool that provides:
- Per-second metrics collection
- Zero configuration monitoring
- Beautiful interactive dashboards
- Health alerting
- Distributed architecture
OEC.SH Netdata Architecture:
┌─────────────────┐
│ Parent Node │
│ (OEC.SH Server) │
│ Port 19999 │
└────────┬────────┘
│
┌────┴────┬────────┬────────┐
│ │ │ │
┌───▼───┐ ┌──▼───┐ ┌──▼───┐ ┌──▼───┐
│Child 1│ │Child 2│ │Child 3│ │Child 4│
│Server1│ │Server2│ │Server3│ │Server4│
└───────┘ └──────┘ └──────┘ └──────┘All your servers stream metrics to the parent node for centralized monitoring.
Automatic Netdata Deployment
Netdata is automatically deployed when:
- First environment is deployed on the server
- You manually click "Deploy Monitoring" in server settings
Deployment Process:
# OEC.SH runs this on your server via SSH
docker run -d --name=netdata \
--pid=host \
--network=host \
-v /etc/passwd:/host/etc/passwd:ro \
-v /etc/group:/host/etc/group:ro \
-v /proc:/host/proc:ro \
-v /sys:/host/sys:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--cap-add SYS_PTRACE \
--security-opt apparmor=unconfined \
-e NETDATA_CLAIM_URL=https://app.netdata.cloud \
-e NETDATA_CLAIM_TOKEN=$YOUR_CLAIM_TOKEN \
netdata/netdata:latestConfiguration Files:
# Netdata configuration
/etc/netdata/netdata.conf
# Streaming configuration (child → parent)
/etc/netdata/stream.conf
# Health alarm configuration
/etc/netdata/health_alarm_notify.confAccess Monitoring Dashboard
Option 1: OEC.SH Embedded Dashboard
- Navigate to server details
- Click Monitoring tab
- View embedded Netdata dashboard
Option 2: Direct Netdata Access
https://your-server-ip:19999Note: Ensure port 19999 is accessible if using direct access.
Monitored Metrics
System Metrics:
- CPU usage (per core and total)
- Memory usage (used, cached, buffers)
- Disk I/O (read/write operations)
- Network traffic (bandwidth, packets, errors)
- System load (1m, 5m, 15m averages)
Docker Metrics (per container):
- Container CPU usage
- Container memory usage
- Container network I/O
- Container disk I/O
- Container health status
Application Metrics (Odoo-specific):
- HTTP request rate
- Response times
- Database connections
- Worker processes
- Error rates
PostgreSQL Metrics:
- Active connections
- Query performance
- Cache hit ratio
- Replication lag (if using read replicas)
- Database size
Health Alerting
Netdata includes pre-configured health alarms:
Default Alerts:
- 🔴 CPU usage > 90% for 10 minutes
- 🔴 RAM usage > 95%
- 🔴 Disk usage > 90%
- 🔴 Disk I/O latency > 50ms
- 🔴 Network errors increasing
- 🟡 High system load (> CPU cores)
Configure Alert Destinations:
- Navigate to organization settings
- Click Notifications tab
- Add webhook URL or email
- Select alert severity levels
Example Webhook Payload:
{
"alert": "high_cpu_usage",
"severity": "critical",
"server": "production-server-1",
"value": 95.2,
"threshold": 90,
"timestamp": "2024-12-11T10:30:00Z",
"message": "CPU usage is critically high on production-server-1"
}Monitoring Best Practices
Resource Planning:
- Monitor trends over 7-30 days
- Scale up when consistent usage > 70%
- Set alerts at 80% to prevent emergencies
Performance Optimization:
- Review slow queries in PostgreSQL metrics
- Monitor Odoo worker utilization
- Check disk I/O patterns for bottlenecks
Capacity Planning:
- Track environment count vs resources
- Monitor per-environment resource usage
- Plan server additions before hitting limits
Troubleshooting
Common issues when adding servers and their solutions.
1. SSH Connection Failed
Symptom: "Connection refused" or "Connection timed out"
Possible Causes:
- Firewall blocking port 22
- SSH service not running
- Wrong IP address or port
- Network connectivity issues
Solutions:
Check SSH service on server:
# Check if SSH is running
sudo systemctl status sshd
# Start SSH if stopped
sudo systemctl start sshd
sudo systemctl enable sshdVerify firewall rules:
# Ubuntu/Debian
sudo ufw status
sudo ufw allow 22/tcp
# Rocky/AlmaLinux/CentOS
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reloadTest connectivity:
# From your local machine
nc -zv your-server-ip 22
# Expected: Connection to your-server-ip port 22 [tcp/ssh] succeeded!
# Test SSH directly
ssh -v root@your-server-ip
# -v flag shows detailed connection debug infoCheck cloud provider firewall (Security Groups, Network ACLs):
- AWS: Check EC2 Security Groups
- DigitalOcean: Check Cloud Firewalls
- Hetzner: Check Firewall rules
2. Authentication Failed
Symptom: "Permission denied" or "Authentication failed"
Possible Causes:
- Wrong password
- SSH key not deployed correctly
- Key passphrase incorrect
- User doesn't have SSH access
Solutions:
For Password Authentication:
# Verify password works manually
ssh root@your-server-ip
# If this fails, reset password via provider consoleFor SSH Key Authentication:
# Verify public key is on server
ssh root@your-server-ip "cat ~/.ssh/authorized_keys"
# Re-deploy public key
ssh-copy-id -i ~/.ssh/your-key.pub root@your-server-ip
# Check key file permissions (must be 600)
ls -l ~/.ssh/your-key
chmod 600 ~/.ssh/your-keyCheck SSH configuration:
# On server, verify SSH accepts keys
sudo cat /etc/ssh/sshd_config | grep "PubkeyAuthentication"
# Should be: PubkeyAuthentication yes
# Verify password auth is enabled (if using password)
sudo cat /etc/ssh/sshd_config | grep "PasswordAuthentication"
# Should be: PasswordAuthentication yesVerify user has shell access:
# Check user's shell
cat /etc/passwd | grep root
# Should end with: /bin/bash or /bin/sh (not /usr/sbin/nologin)3. Docker Not Found
Symptom: "docker: command not found" or "Docker not installed"
Possible Causes:
- Docker not installed
- Docker not in PATH
- Docker service not running
Solutions:
Install Docker (if missing):
# Quick install script (Ubuntu/Debian)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Start Docker
sudo systemctl start docker
sudo systemctl enable dockerVerify Docker installation:
# Check Docker version
docker --version
# Check Docker service
sudo systemctl status docker
# Test Docker
docker run hello-worldAdd user to docker group (if permission denied):
# Add user to docker group
sudo usermod -aG docker $USER
# Apply group changes
newgrp docker
# Verify
docker ps
# Should work without sudo4. Permission Denied Errors
Symptom: "sudo: command not found" or "Permission denied" when running Docker
Possible Causes:
- User not in sudoers
- User not in docker group
- Sudo not installed
Solutions:
Install sudo (if missing):
# Rocky/AlmaLinux/CentOS
su -
dnf install sudo -y
# Ubuntu/Debian (usually pre-installed)
apt install sudo -yAdd user to sudoers:
# Give user NOPASSWD sudo (required for automation)
echo "yourusername ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/yourusername
# Verify
sudo whoami
# Should output: rootAdd user to docker group:
sudo usermod -aG docker yourusername
newgrp dockerUse root user (alternative):
- Change SSH username to "root" in OEC.SH
- Ensure root SSH login is enabled
5. Resource Detection Failed
Symptom: CPU, RAM, or Disk shows 0 or incorrect values
Possible Causes:
- Commands not available
- Non-standard system configuration
- Virtualization limitations
Solutions:
Verify commands exist:
# CPU detection
nproc
# Should output: number of cores
# Memory detection
awk '/^MemTotal:/{printf "%.0f", $2/1024/1024 + 0.5}' /proc/meminfo
# Should output: RAM in GB
# Disk detection
df -BG / | awk 'NR==2{print $2}' | tr -d 'G'
# Should output: disk size in GBManual resource entry:
- In OEC.SH, edit server settings
- Manually enter correct CPU, RAM, disk values
- Save changes
6. Server Unreachable After Adding
Symptom: Server added successfully but shows "Unhealthy" or "Unknown"
Possible Causes:
- Credentials changed after adding
- Server powered off
- Network connectivity lost
- Firewall rules changed
Solutions:
Verify server is running:
# Check if server responds to ping
ping your-server-ip
# Check SSH port
nc -zv your-server-ip 22Update credentials:
- Navigate to server settings in OEC.SH
- Click Update Credentials
- Enter current password or SSH key
- Click Test Connection
- Save if test succeeds
Re-test connection:
- Server details page
- Click Test Connection button
- Review error details
- Fix issues and test again
7. One-Click Secure Fails
Symptom: "Failed to deploy SSH key" during security upgrade
Possible Causes:
- Password authentication disabled on server
~/.sshdirectory has wrong permissions- Disk full (can't write to authorized_keys)
Solutions:
Verify password auth is enabled:
# On server
sudo cat /etc/ssh/sshd_config | grep "PasswordAuthentication"
# Should be: PasswordAuthentication yes (temporarily)
# Restart SSH if you changed it
sudo systemctl restart sshdCheck SSH directory permissions:
# Fix permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
# Create directory if missing
mkdir -p ~/.sshCheck disk space:
df -h /
# Should have at least 1GB freeManual SSH key deployment (if automatic fails):
# On your local machine, generate key
ssh-keygen -t ed25519 -f ~/.ssh/oecsh-server1
# Deploy public key
ssh-copy-id -i ~/.ssh/oecsh-server1.pub root@your-server-ip
# Copy private key content
cat ~/.ssh/oecsh-server1
# In OEC.SH:
# 1. Edit server settings
# 2. Change auth method to "SSH Key"
# 3. Paste private key
# 4. Test connection
# 5. Save8. Netdata Deployment Failed
Symptom: Monitoring container won't start or crashes
Possible Causes:
- Port 19999 already in use
- Docker resource constraints
- Missing kernel capabilities
Solutions:
Check if port is in use:
sudo ss -tlnp | grep 19999
# If in use, stop conflicting service
sudo systemctl stop netdata # if native netdata is runningDeploy Netdata manually:
# Pull latest Netdata image
docker pull netdata/netdata:latest
# Run Netdata container
docker run -d --name=netdata \
--pid=host \
--network=host \
-v /proc:/host/proc:ro \
-v /sys:/host/sys:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--cap-add SYS_PTRACE \
--security-opt apparmor=unconfined \
netdata/netdata:latest
# Verify it's running
docker ps | grep netdata
# Check logs
docker logs netdataDisable AppArmor/SELinux (if security restrictions prevent startup):
# Ubuntu (AppArmor)
sudo aa-complain /usr/sbin/docker
# Rocky/CentOS (SELinux)
sudo setenforce 0
# Make permanent: edit /etc/selinux/config and set SELINUX=permissive9. Server Shows "Needs Setup"
Symptom: Server qualification status is "Needs Setup"
Meaning: Fixable issues detected (usually Docker not installed)
Solutions:
Auto-fix via OEC.SH:
- Navigate to server details
- Click Fix Issues button
- OEC.SH will install Docker and configure system
- Wait for completion (~2-3 minutes)
- Server status changes to "Qualified"
Manual setup:
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo systemctl start docker
sudo systemctl enable docker
# Verify
docker --version
sudo systemctl status docker
# Re-run test in OEC.SH10. High Latency / Slow Deployments
Symptom: Deployments taking 10+ minutes, high network latency
Possible Causes:
- Geographic distance (server in Asia, OEC.SH in Europe)
- Low bandwidth connection
- Network congestion
Solutions:
Choose servers closer to your location:
- Europe → Frankfurt, Amsterdam, London
- US East → New York, Virginia
- US West → San Francisco, Los Angeles
- Asia → Singapore, Tokyo
Test network latency:
# From your local machine to server
ping -c 10 your-server-ip
# From server to OEC.SH
ping -c 10 app.oec.shOptimize Docker image pulls:
# On server, configure Docker registry mirror
sudo mkdir -p /etc/docker
sudo cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://mirror.gcr.io"]
}
EOF
sudo systemctl restart dockerBest Practices
Security
- Always use SSH keys for production - Never rely on passwords for critical servers
- Rotate SSH keys every 90 days - Regenerate and deploy new keys quarterly
- Disable password authentication - Use "One-Click Secure" with password disable option
- Use dedicated user accounts - Avoid using root directly, use sudo user
- Enable firewall - Only allow necessary ports (22, 80, 443)
- Monitor SSH auth logs - Check
/var/log/auth.logfor failed login attempts
Performance
- Use SSD storage - Much faster than HDD for database operations
- Enable swap - Add 2GB swap for better memory management
- Monitor resource usage - Keep CPU/RAM below 70% for stable operations
- Scale horizontally - Add more servers instead of over-provisioning single server
- Use local Docker registry - Cache images to speed up deployments
Maintenance
- Regular OS updates - Update packages monthly
- Docker updates - Keep Docker updated to latest stable version
- Monitor disk space - Set alerts for 80% disk usage
- Backup server configuration - Document firewall, network, SSH settings
- Test disaster recovery - Practice server restoration quarterly
Cost Optimization
- Right-size servers - Don't over-provision, use autoscaling
- Use spot instances - For non-critical dev/staging (AWS, GCP)
- Regional pricing - Some regions cost 30-50% less
- Reserved instances - Commit to 1-3 years for 30-60% savings
- Monitor idle resources - Stop unused environments to free resources
Next Steps
Now that your server is added and configured, you're ready to:
- Configure Storage Provider - Required for backups
- Create Your First Project - Set up your Odoo codebase
- Deploy First Environment - Launch your Odoo instance
- Configure Custom Domain - Add your production domain
- Setup Monitoring - Configure alerts and dashboards
API Reference
Create Server
Endpoint: POST /api/v1/vms
Permission: org.servers.create
Request Body:
{
"organization_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "production-server-1",
"provider": "custom",
"region": "Frankfurt, Germany",
"ipv4_address": "203.0.113.100",
"ipv6_address": null,
"fqdn": "server1.example.com",
"connection_host_type": "auto",
"ssh_port": 22,
"ssh_username": "root",
"ssh_auth_method": "password",
"ssh_password": "your-secure-password",
"cpu_cores": 4,
"memory_gb": 8,
"disk_gb": 160,
"max_projects": 8
}Response: 201 Created
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"organization_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_name": "My Organization",
"name": "production-server-1",
"provider": "custom",
"region": "Frankfurt, Germany",
"ipv4_address": "203.0.113.100",
"ipv6_address": null,
"fqdn": "server1.example.com",
"hostname": null,
"connection_host": "server1.example.com",
"ssh_port": 22,
"ssh_username": "root",
"ssh_auth_method": "password",
"status": "running",
"health_status": "unknown",
"cpu_cores": 4,
"memory_gb": 8,
"disk_gb": 160,
"max_projects": 8,
"environment_count": 0,
"running_environment_count": 0,
"created_at": "2024-12-11T10:30:00Z",
"updated_at": "2024-12-11T10:30:00Z"
}cURL Example:
curl -X POST https://app.oec.sh/api/v1/vms \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"organization_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "production-server-1",
"provider": "custom",
"region": "Frankfurt, Germany",
"ipv4_address": "203.0.113.100",
"ssh_port": 22,
"ssh_username": "root",
"ssh_auth_method": "password",
"ssh_password": "your-password",
"cpu_cores": 4,
"memory_gb": 8,
"disk_gb": 160,
"max_projects": 8
}'Test Server Connection
Endpoint: POST /api/v1/vms/{vm_id}/test-connection
Permission: org.servers.test
Request: No body required
Response: 200 OK
{
"vm_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"vm_name": "production-server-1",
"organization_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_name": "My Organization",
"connection_host": "203.0.113.100",
"ssh_port": 22,
"ssh_username": "root",
"auth_method": "password",
"status": "success",
"message": "Connection successful",
"detected": {
"hostname": "ubuntu-s-2vcpu-4gb-fra1-01",
"os_type": "Ubuntu",
"os_version": "22.04",
"docker_status": "running",
"docker_version": "24.0.7",
"cpu_cores": 2,
"memory_gb": 4,
"disk_gb": 80,
"provider": "digitalocean",
"region": "Frankfurt 1",
"is_root": false,
"sudo_available": true,
"ssh_sudo_mode": "sudo"
}
}cURL Example:
curl -X POST https://app.oec.sh/api/v1/vms/7c9e6679-7425-40de-944b-e07fc1f90ae7/test-connection \
-H "Authorization: Bearer YOUR_API_TOKEN"Secure Server (One-Click)
Endpoint: POST /api/v1/vms/{vm_id}/secure
Permission: org.servers.secure
Request Body (optional):
{
"disable_password_auth": true
}Response: 200 OK
{
"message": "Server successfully secured with SSH key authentication",
"vm_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"vm_name": "production-server-1",
"previous_auth_method": "password",
"new_auth_method": "ssh_key",
"key_verified": true,
"secured_at": "2024-12-11T11:00:00Z",
"password_cleared": true,
"server_password_auth_disabled": true,
"private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----",
"public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAbc... paasportal-production-server-1",
"key_type": "ed25519"
}cURL Example:
curl -X POST https://app.oec.sh/api/v1/vms/7c9e6679-7425-40de-944b-e07fc1f90ae7/secure \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "disable_password_auth": true }'Important: Save the private_key from the response immediately. It will never be shown again.
Related Documentation
- Configure Storage Provider - Set up backup storage
- Create Your First Project - Initialize Odoo project
- Deploy First Environment - Launch Odoo instance
- Server Management - Detailed server operations
- Server Actions - Start, stop, restart, delete
- Netdata Monitoring - Advanced monitoring setup
- Troubleshooting Servers - Common server issues
Last Updated: December 11, 2024 Sprint: Phase 1 - Sprint 2E42 Document Version: 1.0 Estimated Reading Time: 25 minutes